Browse Source

增加埋点

zk 1 year ago
parent
commit
6eec0484aa
38 changed files with 729 additions and 62 deletions
  1. 3 0
      app/src/main/java/com/datarecovery/master/data/api/AtmobApi.java
  2. 6 2
      app/src/main/java/com/datarecovery/master/data/api/bean/MemberGoodsBean.java
  3. 1 1
      app/src/main/java/com/datarecovery/master/data/api/bean/OrderBean.java
  4. 8 0
      app/src/main/java/com/datarecovery/master/data/consts/Constants.java
  5. 59 0
      app/src/main/java/com/datarecovery/master/data/consts/EventId.java
  6. 33 2
      app/src/main/java/com/datarecovery/master/data/repositories/AccountRepository.java
  7. 2 7
      app/src/main/java/com/datarecovery/master/data/repositories/DeviceFuncRepository.java
  8. 1 3
      app/src/main/java/com/datarecovery/master/data/repositories/MemberRepository.java
  9. 2 9
      app/src/main/java/com/datarecovery/master/data/repositories/PayRepository.java
  10. 10 0
      app/src/main/java/com/datarecovery/master/dialog/AgreementDialog.java
  11. 3 2
      app/src/main/java/com/datarecovery/master/dialog/AlipayQrCodeDialog.java
  12. 3 2
      app/src/main/java/com/datarecovery/master/dialog/WechatPayQrCodeDialog.java
  13. 69 0
      app/src/main/java/com/datarecovery/master/handler/EventHelper.java
  14. 1 1
      app/src/main/java/com/datarecovery/master/module/audiorecover/AudioRecoverActivity.java
  15. 1 1
      app/src/main/java/com/datarecovery/master/module/filerecover/FileRecoverActivity.java
  16. 2 2
      app/src/main/java/com/datarecovery/master/module/homepage/HomePageViewModel.java
  17. 1 1
      app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverActivity.java
  18. 8 1
      app/src/main/java/com/datarecovery/master/module/login/LoginActivity.java
  19. 33 5
      app/src/main/java/com/datarecovery/master/module/login/LoginViewModel.java
  20. 8 0
      app/src/main/java/com/datarecovery/master/module/main/MainActivity.java
  21. 20 0
      app/src/main/java/com/datarecovery/master/module/main/MainViewModel.java
  22. 1 1
      app/src/main/java/com/datarecovery/master/module/member/GoodsItemAdapter.java
  23. 3 2
      app/src/main/java/com/datarecovery/master/module/member/MemberActivity.java
  24. 52 8
      app/src/main/java/com/datarecovery/master/module/member/MemberViewModel.java
  25. 41 0
      app/src/main/java/com/datarecovery/master/module/member/bean/PayInfo.java
  26. 4 4
      app/src/main/java/com/datarecovery/master/module/mine/MineViewModel.java
  27. 5 0
      app/src/main/java/com/datarecovery/master/module/order/OrderItemAdapter.java
  28. 1 1
      app/src/main/java/com/datarecovery/master/module/splash/SplashActivity.java
  29. 1 1
      app/src/main/java/com/datarecovery/master/module/videorecover/VideoRecoverActivity.java
  30. 44 1
      app/src/main/java/com/datarecovery/master/module/wxrecover/WeChatRecoverActivity.java
  31. 32 1
      app/src/main/java/com/datarecovery/master/module/wxrecover/WeChatViewModel.java
  32. 2 2
      app/src/main/java/com/datarecovery/master/utils/FilePermissionHelper.java
  33. 12 0
      app/src/main/java/com/datarecovery/master/utils/Maps.java
  34. 130 0
      app/src/main/java/com/datarecovery/master/utils/OrderReportHelper.java
  35. 117 0
      app/src/main/java/com/datarecovery/master/utils/RxHttpHandler.java
  36. 6 1
      app/src/main/res/layout/dialog_agreement.xml
  37. 2 1
      app/src/main/res/layout/item_order.xml
  38. 2 0
      app/src/main/res/values/strings.xml

+ 3 - 0
app/src/main/java/com/datarecovery/master/data/api/AtmobApi.java

@@ -32,6 +32,9 @@ public interface AtmobApi {
     @POST("/project/recover/v1/user/login")
     @POST("/project/recover/v1/user/login")
     Single<BaseResponse<LoginResponse>> loginUserLogin(@Body LoginRequest request);
     Single<BaseResponse<LoginResponse>> loginUserLogin(@Body LoginRequest request);
 
 
+    @POST("/project/recover/v1/user/logout")
+    Single<BaseResponse<Object>> userLogout(@Body BaseRequest request);
+
     @POST("/project/recover/v1/order/page")
     @POST("/project/recover/v1/order/page")
     Single<BaseResponse<OrderPageResponse>> orderPage(@Body OrderPageRequest request);
     Single<BaseResponse<OrderPageResponse>> orderPage(@Body OrderPageRequest request);
 
 

+ 6 - 2
app/src/main/java/com/datarecovery/master/data/api/bean/MemberGoodsBean.java

@@ -71,8 +71,12 @@ public class MemberGoodsBean extends BaseObservable {
         return auths;
         return auths;
     }
     }
 
 
-    public float getAmount() {
-        return amount / 100f;
+    public int getAmount() {
+        return amount;
+    }
+
+    public float getRMBAmount() {
+        return (float) (amount / 100.0);
     }
     }
 
 
     public float getOriginalAmount() {
     public float getOriginalAmount() {

+ 1 - 1
app/src/main/java/com/datarecovery/master/data/api/bean/OrderBean.java

@@ -42,7 +42,7 @@ public class OrderBean {
         if (permanent) {
         if (permanent) {
             return "永久有效";
             return "永久有效";
         } else {
         } else {
-            return DateUtil.formatNormalDate(DateUtil.YYYY_MM_DD, endTimestamp);
+            return DateUtil.formatNormalDate(DateUtil.YYYY_MM_DD_HH_MM_SS, endTimestamp);
         }
         }
     }
     }
 
 

+ 8 - 0
app/src/main/java/com/datarecovery/master/data/consts/Constants.java

@@ -19,4 +19,12 @@ public class Constants {
     public static final String USER_AGREEMENT = "http://cdn.myaskai.cn/manyue/static/wjsjhfds-manyue-clause.html";
     public static final String USER_AGREEMENT = "http://cdn.myaskai.cn/manyue/static/wjsjhfds-manyue-clause.html";
 
 
 
 
+    //未登录
+    public static final int ERROR_CODE_NO_LOGIN_ERROR = 1006;
+
+    public static final int PAYMENT_WAY_WECHAT = 1;
+    public static final int PAYMENT_WAY_WECHAT_SCAN = 2;
+    public static final int PAYMENT_WAY_ALIPAY = 3;
+    public static final int PAYMENT_WAY_ALIPAY_SCAN = 4;
+
 }
 }

+ 59 - 0
app/src/main/java/com/datarecovery/master/data/consts/EventId.java

@@ -0,0 +1,59 @@
+package com.datarecovery.master.data.consts;
+
+public interface EventId {
+
+    String EVENT_ID = "id";
+    String hf1000101 = "hf1000101"; // 启动页-隐私弹窗-同意并继续
+    String hf1000201 = "hf1000201"; // 启动页-温馨提示-同意
+    String hf1000301 = "hf1000301"; // 登录跳转页   带跳转页面ID:我的hf11018,微信消息恢复hf11011,微信好友恢复hf11009,图片恢复hf11001,文件恢复hf11003,视频恢复hf11005,音频恢复hf11007,图片清除hf11013
+    String hf1000302 = "hf1000302"; // 登录-登录按钮-点击
+    String hf1000303 = "hf1000303"; // 登录-登录按钮-登录成功
+    String hf1000304 = "hf1000304"; // 登录-登录按钮-登录失败 ID:请勾选并同意协议hf11019,验证码错误hf11020,网络错误hf11021,其他原因hf11022
+    String hf1000305 = "hf1000305"; // 获取验证码-验证码报错  ID:手机号错误hf11034,其他原因hf11022
+    String hf1000401 = "hf1000401"; // 申请文件管理权限-取消
+    String hf1000402 = "hf1000402"; // 申请文件管理权限-授权权限
+    String hf1000403 = "hf1000403"; // 申请文件目录权限-等会在说
+    String hf1000404 = "hf1000404"; // 申请文件目录权限-授权权限
+    String hf1000501 = "hf1000501"; // 微信消息恢复-进入服务详情页
+    String hf1000502 = "hf1000502"; // 微信消息恢复-使用服务
+    String hf1000503 = "hf1000503"; // 微信好友恢复-进入服务详情页
+    String hf1000504 = "hf1000504"; // 微信好友恢复-使用服务
+    String hf1000505 = "hf1000505"; // 图片恢复-进入服务详情页
+    String hf1000506 = "hf1000506"; // 图片恢复-使用服务
+    String hf1000507 = "hf1000507"; // 文件恢复-进入服务详情页
+    String hf1000508 = "hf1000508"; // 文件恢复-使用服务
+    String hf1000509 = "hf1000509"; // 视频恢复-进入服务详情页
+    String hf1000510 = "hf1000510"; // 视频恢复-使用服务
+    String hf1000511 = "hf1000511"; // 音频恢复-进入服务详情页
+    String hf1000512 = "hf1000512"; // 音频恢复-使用服务
+    String hf1000513 = "hf1000513"; // 图片清除-进入服务详情页
+    String hf1000514 = "hf1000514"; // 图片清除-使用服务
+    String hf1000515 = "hf1000515"; // 底部导航栏-点击 ID:首页hf11015,案例hf11016,我的hf11018
+    String hf1000601 = "hf1000601"; // 服务详情-价格分类-点击 ID:超级恢复hf11035,微信消息恢复hf11011,微信好友恢复hf11009,图片恢复hf11001,文件恢复hf11003,视频恢复hf11005,音频恢复hf11007,图片清除hf11013
+    String hf1000602 = "hf1000602"; // 服务详情-支付按钮-点击
+    String hf1000603 = "hf1000603"; // 服务详情-支付按钮-选择支付方式 ID:支付宝支付hf11023,支付宝扫码支付hf11024
+    String hf1000604 = "hf1000604"; // 服务详情-支付成功-带页面跳转ID ID:微信消息恢复hf11011,微信好友恢复hf11009,图片恢复hf11001,文件恢复hf11003,视频恢复hf11005,音频恢复hf11007,图片清除hf11013
+    String hf1000605 = "hf1000605"; // 服务详情-支付成功-带价格服务类型ID ID:单功能一年hf11025,超级恢复一年hf11026,永久清除hf11027
+    String hf1000606 = "hf1000606"; // 服务详情-支付失败 ID:放弃支付hf11028,网络错误hf11021,其他原因hf11022
+    String hf1000607 = "hf1000607"; // 服务详情-挽留弹窗-关闭图标-点击
+    String hf1000608 = "hf1000608"; // 服务详情-挽留弹窗-立即恢复按钮-点击
+    String hf1000609 = "hf1000609"; // 服务详情-页面停留时长 加页面ID:微信消息恢复hf11011,微信好友恢复hf11009,图片恢复hf11001,文件恢复hf11003,视频恢复hf11005,音频恢复hf11007,图片清除hf11013
+    String hf1000701 = "hf1000701"; // 各功能页面停留时长 加页面ID:微信消息恢复hf11012,微信好友恢复hf11010,图片恢复hf11002,文件恢复hf11004,视频恢复hf11006,音频恢复hf11008,图片清除hf11014
+    String hf1000801 = "hf1000801"; // 案例-案例详情
+    String hf1000901 = "hf1000901"; // 订单-点击
+    String hf1001101 = "hf1001101"; // 我的-banner图-点击
+    String hf1001102 = "hf1001102"; // 我的-关于我们-点击
+    String hf1001103 = "hf1001103"; // 我的-关于我们-用户协议
+    String hf1001104 = "hf1001104"; // 我的-关于我们-隐私协议
+    String hf1001105 = "hf1001105"; // 我的-意见反馈-点击
+    String hf1001106 = "hf1001106"; // 我的-意见反馈-提交成功 带反馈内容
+    String hf1001107 = "hf1001107"; // 我的-意见反馈-提交失败 ID:网络错误hf11021,其他原因hf11022
+    String hf1001108 = "hf1001108"; // 我的-联系客服-点击
+    String hf1001109 = "hf1001109"; // 我的-注销账号-点击
+    String hf1001110 = "hf1001110"; // 我的-注销账号-二次确认弹窗-确认
+    String hf1001111 = "hf1001111"; // 我的-注销账号-二次确认弹窗-取消
+    String hf1001112 = "hf1001112"; // 我的-退出账号-点击
+    String hf1001113 = "hf1001113"; // 我的-退出账号-二次确认弹窗-确认
+    String hf1001114 = "hf1001114"; // 我的-退出账号-二次确认弹窗-取消
+
+}

+ 33 - 2
app/src/main/java/com/datarecovery/master/data/repositories/AccountRepository.java

@@ -6,20 +6,26 @@ import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.Transformations;
 import androidx.lifecycle.Transformations;
 
 
-import com.atmob.app.lib.handler.RxHttpHandler;
 import com.atmob.common.data.KVUtils;
 import com.atmob.common.data.KVUtils;
 import com.atmob.common.logging.AtmobLog;
 import com.atmob.common.logging.AtmobLog;
+import com.datarecovery.master.R;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.AtmobApi;
+import com.datarecovery.master.data.api.request.BaseRequest;
 import com.datarecovery.master.data.api.request.LoginRequest;
 import com.datarecovery.master.data.api.request.LoginRequest;
 import com.datarecovery.master.data.api.request.SendCodeRequest;
 import com.datarecovery.master.data.api.request.SendCodeRequest;
 import com.datarecovery.master.data.api.response.LoginResponse;
 import com.datarecovery.master.data.api.response.LoginResponse;
 import com.datarecovery.master.data.consts.ErrorCode;
 import com.datarecovery.master.data.consts.ErrorCode;
 import com.datarecovery.master.utils.BoxingUtil;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.RxHttpHandler;
+import com.datarecovery.master.utils.ToastUtil;
 
 
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 
 
+import atmob.reactivex.rxjava3.annotations.NonNull;
 import atmob.reactivex.rxjava3.core.Single;
 import atmob.reactivex.rxjava3.core.Single;
+import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.disposables.Disposable;
 import atmob.rxjava.utils.RxJavaUtil;
 import atmob.rxjava.utils.RxJavaUtil;
 
 
 @Singleton
 @Singleton
@@ -110,12 +116,31 @@ public class AccountRepository {
                 });
                 });
     }
     }
 
 
+    public void requestUserLogout() {
+        userLogout().subscribe(new SingleObserver<Object>() {
+            @Override
+            public void onSubscribe(@NonNull Disposable d) {
+
+            }
+
+            @Override
+            public void onSuccess(@NonNull Object o) {
+                logout();
+            }
+
+            @Override
+            public void onError(@NonNull Throwable e) {
+                ToastUtil.show(R.string.account_logout_fail, ToastUtil.LENGTH_SHORT);
+            }
+        });
+    }
+
     public void logout() {
     public void logout() {
         if (!BoxingUtil.boxing(isLogin.getValue())) {
         if (!BoxingUtil.boxing(isLogin.getValue())) {
             return;
             return;
         }
         }
         token = null;
         token = null;
-        deviceFuncRepository.clearAuths();
+        deviceFuncRepository.refreshFuncAuths();
         payRepository.refreshOrderPageList();
         payRepository.refreshOrderPageList();
         KVUtils.getDefault().putString(KEY_LOGIN_PHONE_NUM, "");
         KVUtils.getDefault().putString(KEY_LOGIN_PHONE_NUM, "");
         KVUtils.getDefault().putString(KEY_LOGIN_TOKEN, "");
         KVUtils.getDefault().putString(KEY_LOGIN_TOKEN, "");
@@ -125,6 +150,12 @@ public class AccountRepository {
         }
         }
     }
     }
 
 
+    private Single<Object> userLogout() {
+        return atmobApi.userLogout(new BaseRequest())
+                .compose(RxHttpHandler.handle(true))
+                .compose(RxJavaUtil.SingleSchedule.io2Main());
+    }
+
 
 
     public static class RequestCodeTooOftenException extends Exception {
     public static class RequestCodeTooOftenException extends Exception {
     }
     }

+ 2 - 7
app/src/main/java/com/datarecovery/master/data/repositories/DeviceFuncRepository.java

@@ -3,15 +3,12 @@ package com.datarecovery.master.data.repositories;
 
 
 import android.text.TextUtils;
 import android.text.TextUtils;
 
 
-import com.atmob.app.lib.handler.RxHttpHandler;
-import com.atmob.common.text.TextUtil;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.request.BaseRequest;
 import com.datarecovery.master.data.api.request.BaseRequest;
-import com.datarecovery.master.data.api.request.FindOrderRequest;
-import com.datarecovery.master.data.api.response.FindOrderResponse;
 import com.datarecovery.master.data.api.response.FuncAuthsResponse;
 import com.datarecovery.master.data.api.response.FuncAuthsResponse;
 import com.datarecovery.master.data.api.response.UserCaseResponse;
 import com.datarecovery.master.data.api.response.UserCaseResponse;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.module.member.MemberType;
+import com.datarecovery.master.utils.RxHttpHandler;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
@@ -71,9 +68,7 @@ public class DeviceFuncRepository {
                     public void onSuccess(@NonNull FuncAuthsResponse funcAuthsResponse) {
                     public void onSuccess(@NonNull FuncAuthsResponse funcAuthsResponse) {
                         refreshFunAuthsFlag = false;
                         refreshFunAuthsFlag = false;
                         authsList.clear();
                         authsList.clear();
-                        if (!TextUtils.isEmpty(AccountRepository.token)) {
-                            authsList.addAll(funcAuthsResponse.getAuths());
-                        }
+                        authsList.addAll(funcAuthsResponse.getAuths());
                     }
                     }
 
 
                     @Override
                     @Override

+ 1 - 3
app/src/main/java/com/datarecovery/master/data/repositories/MemberRepository.java

@@ -1,18 +1,16 @@
 package com.datarecovery.master.data.repositories;
 package com.datarecovery.master.data.repositories;
 
 
 
 
-import com.atmob.app.lib.handler.RxHttpHandler;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.request.MemberDetailRequest;
 import com.datarecovery.master.data.api.request.MemberDetailRequest;
 import com.datarecovery.master.data.api.request.MemberPayRequest;
 import com.datarecovery.master.data.api.request.MemberPayRequest;
-import com.datarecovery.master.data.api.request.OrderPageRequest;
 import com.datarecovery.master.data.api.request.PaymentStatusRequest;
 import com.datarecovery.master.data.api.request.PaymentStatusRequest;
 import com.datarecovery.master.data.api.response.MemberDetailResponse;
 import com.datarecovery.master.data.api.response.MemberDetailResponse;
 import com.datarecovery.master.data.api.response.MemberPayResponse;
 import com.datarecovery.master.data.api.response.MemberPayResponse;
-import com.datarecovery.master.data.api.response.OrderPageResponse;
 import com.datarecovery.master.data.api.response.PaymentStatusResponse;
 import com.datarecovery.master.data.api.response.PaymentStatusResponse;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.utils.BoxingUtil;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.RxHttpHandler;
 
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
 
 

+ 2 - 9
app/src/main/java/com/datarecovery/master/data/repositories/PayRepository.java

@@ -1,28 +1,24 @@
 package com.datarecovery.master.data.repositories;
 package com.datarecovery.master.data.repositories;
 
 
 
 
-import android.text.TextUtils;
 
 
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.MutableLiveData;
 
 
-import com.atmob.app.lib.handler.RxHttpHandler;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.AtmobApi;
 import com.datarecovery.master.data.api.bean.OrderBean;
 import com.datarecovery.master.data.api.bean.OrderBean;
 import com.datarecovery.master.data.api.request.FindOrderRequest;
 import com.datarecovery.master.data.api.request.FindOrderRequest;
 import com.datarecovery.master.data.api.request.OrderPageRequest;
 import com.datarecovery.master.data.api.request.OrderPageRequest;
 import com.datarecovery.master.data.api.response.FindOrderResponse;
 import com.datarecovery.master.data.api.response.FindOrderResponse;
 import com.datarecovery.master.data.api.response.OrderPageResponse;
 import com.datarecovery.master.data.api.response.OrderPageResponse;
+import com.datarecovery.master.utils.RxHttpHandler;
 
 
 import java.util.List;
 import java.util.List;
 
 
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 
 
-import atmob.reactivex.rxjava3.annotations.NonNull;
 import atmob.reactivex.rxjava3.core.Single;
 import atmob.reactivex.rxjava3.core.Single;
-import atmob.reactivex.rxjava3.core.SingleObserver;
-import atmob.reactivex.rxjava3.disposables.Disposable;
 import atmob.rxjava.utils.RxJavaUtil;
 import atmob.rxjava.utils.RxJavaUtil;
 
 
 @Singleton
 @Singleton
@@ -49,10 +45,7 @@ public class PayRepository {
         return atmobApi.orderPage(new OrderPageRequest(limit, offset))
         return atmobApi.orderPage(new OrderPageRequest(limit, offset))
                 .compose(RxHttpHandler.handle(true))
                 .compose(RxHttpHandler.handle(true))
                 .compose(RxJavaUtil.SingleSchedule.io2Main())
                 .compose(RxJavaUtil.SingleSchedule.io2Main())
-                .doOnSuccess(orderPageResponse -> {
-                    orderList.setValue(orderPageResponse.getList());
-                });
-
+                .doOnSuccess(orderPageResponse -> orderList.setValue(orderPageResponse.getList()));
     }
     }
 
 
     public Single<FindOrderResponse> findOrder(String[] auths) {
     public Single<FindOrderResponse> findOrder(String[] auths) {

+ 10 - 0
app/src/main/java/com/datarecovery/master/dialog/AgreementDialog.java

@@ -13,7 +13,9 @@ import androidx.annotation.NonNull;
 import com.atmob.app.lib.base.BaseDialog;
 import com.atmob.app.lib.base.BaseDialog;
 import com.datarecovery.master.R;
 import com.datarecovery.master.R;
 import com.datarecovery.master.data.consts.Constants;
 import com.datarecovery.master.data.consts.Constants;
+import com.datarecovery.master.data.consts.EventId;
 import com.datarecovery.master.databinding.DialogAgreementBinding;
 import com.datarecovery.master.databinding.DialogAgreementBinding;
+import com.datarecovery.master.handler.EventHelper;
 import com.datarecovery.master.module.browser.BrowserActivity;
 import com.datarecovery.master.module.browser.BrowserActivity;
 
 
 
 
@@ -28,6 +30,13 @@ public class AgreementDialog extends BaseDialog<DialogAgreementBinding> {
         setCancelable(false);
         setCancelable(false);
         binding.setIsTwoStep(false);
         binding.setIsTwoStep(false);
         binding.setOnAgreeClickListener(v -> {
         binding.setOnAgreeClickListener(v -> {
+            EventHelper.report(EventId.hf1000101);
+            dismiss();
+            if (agreementAction != null) {
+                agreementAction.onAgree();
+            }
+        });
+        binding.setOnStepAgreeClickListener(v -> {
             dismiss();
             dismiss();
             if (agreementAction != null) {
             if (agreementAction != null) {
                 agreementAction.onAgree();
                 agreementAction.onAgree();
@@ -38,6 +47,7 @@ public class AgreementDialog extends BaseDialog<DialogAgreementBinding> {
 
 
         });
         });
         binding.setOnStepTwoDisagreeClickListener(v -> {
         binding.setOnStepTwoDisagreeClickListener(v -> {
+            EventHelper.report(EventId.hf1000201);
             dismiss();
             dismiss();
             if (agreementAction != null) {
             if (agreementAction != null) {
                 agreementAction.onDisagree();
                 agreementAction.onDisagree();

+ 3 - 2
app/src/main/java/com/datarecovery/master/dialog/AlipayQrCodeDialog.java

@@ -11,6 +11,7 @@ import androidx.annotation.NonNull;
 import com.atmob.app.lib.base.BaseDialog;
 import com.atmob.app.lib.base.BaseDialog;
 import com.atmob.common.ui.SizeUtil;
 import com.atmob.common.ui.SizeUtil;
 import com.datarecovery.master.R;
 import com.datarecovery.master.R;
+import com.datarecovery.master.data.consts.Constants;
 import com.datarecovery.master.databinding.DialogAlipayQrCodeBinding;
 import com.datarecovery.master.databinding.DialogAlipayQrCodeBinding;
 import com.datarecovery.master.module.member.MemberViewModel;
 import com.datarecovery.master.module.member.MemberViewModel;
 
 
@@ -49,7 +50,7 @@ public class AlipayQrCodeDialog extends BaseDialog<DialogAlipayQrCodeBinding> {
         super.onDismiss();
         super.onDismiss();
         if (queryOrderDisposable != null && !queryOrderDisposable.isDisposed()) {
         if (queryOrderDisposable != null && !queryOrderDisposable.isDisposed()) {
             queryOrderDisposable.dispose();
             queryOrderDisposable.dispose();
-            memberViewModel.queryOrderStatus(orderId, true);
+            memberViewModel.queryOrderStatus(orderId, Constants.PAYMENT_WAY_ALIPAY_SCAN, true, true);
         }
         }
         binding.alipayQrCodeWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
         binding.alipayQrCodeWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
     }
     }
@@ -57,7 +58,7 @@ public class AlipayQrCodeDialog extends BaseDialog<DialogAlipayQrCodeBinding> {
     public void show(String qrCodeHtml, String orderId, MemberViewModel memberViewModel) {
     public void show(String qrCodeHtml, String orderId, MemberViewModel memberViewModel) {
         this.memberViewModel = memberViewModel;
         this.memberViewModel = memberViewModel;
         this.orderId = orderId;
         this.orderId = orderId;
-        this.queryOrderDisposable = memberViewModel.queryOrderStatus(orderId, false);
+        this.queryOrderDisposable = memberViewModel.queryOrderStatus(orderId, Constants.PAYMENT_WAY_ALIPAY_SCAN, false, true);
         binding.alipayQrCodeWebView.loadDataWithBaseURL(null, HTML_TEMPLATE.replace("${qr_code_html}", qrCodeHtml), "text/html", "utf-8", null);
         binding.alipayQrCodeWebView.loadDataWithBaseURL(null, HTML_TEMPLATE.replace("${qr_code_html}", qrCodeHtml), "text/html", "utf-8", null);
         super.show();
         super.show();
     }
     }

+ 3 - 2
app/src/main/java/com/datarecovery/master/dialog/WechatPayQrCodeDialog.java

@@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
 
 
 import com.atmob.app.lib.base.BaseDialog;
 import com.atmob.app.lib.base.BaseDialog;
 import com.datarecovery.master.R;
 import com.datarecovery.master.R;
+import com.datarecovery.master.data.consts.Constants;
 import com.datarecovery.master.databinding.DialogWechatPayQrCodeBinding;
 import com.datarecovery.master.databinding.DialogWechatPayQrCodeBinding;
 import com.datarecovery.master.module.member.MemberViewModel;
 import com.datarecovery.master.module.member.MemberViewModel;
 import com.datarecovery.master.utils.QrCodeUtil;
 import com.datarecovery.master.utils.QrCodeUtil;
@@ -33,7 +34,7 @@ public class WechatPayQrCodeDialog extends BaseDialog<DialogWechatPayQrCodeBindi
         binding.wechatPayQrCode.setImageBitmap(null);
         binding.wechatPayQrCode.setImageBitmap(null);
         if (queryOrderDisposable != null && !queryOrderDisposable.isDisposed()) {
         if (queryOrderDisposable != null && !queryOrderDisposable.isDisposed()) {
             queryOrderDisposable.dispose();
             queryOrderDisposable.dispose();
-            memberViewModel.queryOrderStatus(orderId, true);
+            memberViewModel.queryOrderStatus(orderId, Constants.PAYMENT_WAY_WECHAT_SCAN, true, true);
         }
         }
         if (generateQRDisposable != null && !generateQRDisposable.isDisposed()) {
         if (generateQRDisposable != null && !generateQRDisposable.isDisposed()) {
             generateQRDisposable.dispose();
             generateQRDisposable.dispose();
@@ -43,7 +44,7 @@ public class WechatPayQrCodeDialog extends BaseDialog<DialogWechatPayQrCodeBindi
     public void show(String qrCodeData, String orderId, MemberViewModel memberViewModel) {
     public void show(String qrCodeData, String orderId, MemberViewModel memberViewModel) {
         this.memberViewModel = memberViewModel;
         this.memberViewModel = memberViewModel;
         this.orderId = orderId;
         this.orderId = orderId;
-        this.queryOrderDisposable = memberViewModel.queryOrderStatus(orderId, false);
+        this.queryOrderDisposable = memberViewModel.queryOrderStatus(orderId, Constants.PAYMENT_WAY_WECHAT_SCAN, false, true);
         if (generateQRDisposable != null && !generateQRDisposable.isDisposed()) {
         if (generateQRDisposable != null && !generateQRDisposable.isDisposed()) {
             generateQRDisposable.dispose();
             generateQRDisposable.dispose();
         }
         }

+ 69 - 0
app/src/main/java/com/datarecovery/master/handler/EventHelper.java

@@ -0,0 +1,69 @@
+package com.datarecovery.master.handler;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import com.datarecovery.master.data.consts.Constants;
+import com.datarecovery.master.sdk.gravity.GravityHelper;
+import com.datarecovery.master.utils.ToastUtil;
+
+import org.json.JSONObject;
+
+import java.util.Map;
+
+public class EventHelper {
+
+    private static final boolean isToastReport = false;
+
+    private static Handler MAIN_HANDLER;
+
+    static {
+        if (isToastReport) {
+            MAIN_HANDLER = new Handler(Looper.getMainLooper());
+        }
+    }
+
+
+    public static void timeEvent(String eventId) {
+        GravityHelper.timeEvent(eventId);
+    }
+
+    public static void report(String eventId) {
+        report(eventId, null);
+    }
+
+    public static void report(String eventId, Map<String, Object> params) {
+        if (isToastReport) {
+            MAIN_HANDLER.post(() -> {
+                StringBuilder sb = new StringBuilder();
+                sb.append(eventId);
+                if (params != null) {
+                    sb.append(" ");
+                    sb.append(new JSONObject(params));
+                }
+                ToastUtil.show(sb.toString(), ToastUtil.LENGTH_SHORT);
+            });
+        }
+        GravityHelper.report(eventId, params);
+    }
+
+    public static void reportPay(int priceFen, String orderId, int payWay, String itemName) {
+        String payWayName = "未知";
+        switch (payWay) {
+            case Constants.PAYMENT_WAY_WECHAT:
+            case Constants.PAYMENT_WAY_WECHAT_SCAN:
+                payWayName = "微信";
+                break;
+            case Constants.PAYMENT_WAY_ALIPAY:
+            case Constants.PAYMENT_WAY_ALIPAY_SCAN:
+                payWayName = "支付宝";
+                break;
+        }
+        if (isToastReport) {
+            MAIN_HANDLER.post(() -> ToastUtil.show("payment: priceFen = [" + priceFen + "], orderId = ["
+                            + orderId + "], payWay = [" + payWay + "], itemName = [" + itemName + "]",
+                    ToastUtil.LENGTH_SHORT));
+        }
+        GravityHelper.reportPay(priceFen, orderId, itemName, payWayName);
+    }
+}

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/audiorecover/AudioRecoverActivity.java

@@ -68,7 +68,7 @@ public class AudioRecoverActivity extends BaseActivity<ActivityAudioRecoverBindi
     }
     }
 
 
     private void initPermission() {
     private void initPermission() {
-        new FilePermissionHelper().requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+        new FilePermissionHelper().requestDataFilePermission(this, "hf11007", new FilePermissionHelper.NextStepCallback() {
             @Override
             @Override
             public void onNextStep() {
             public void onNextStep() {
                 audioRecoverViewModel.startAudioScanning();
                 audioRecoverViewModel.startAudioScanning();

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/filerecover/FileRecoverActivity.java

@@ -57,7 +57,7 @@ public class FileRecoverActivity extends BaseActivity<ActivityFileRecoverBinding
     }
     }
 
 
     private void initPermission() {
     private void initPermission() {
-        new FilePermissionHelper().requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+        new FilePermissionHelper().requestDataFilePermission(this, "hf11003", new FilePermissionHelper.NextStepCallback() {
             @Override
             @Override
             public void onNextStep() {
             public void onNextStep() {
                 fileRecoverViewModel.startFileScanning();
                 fileRecoverViewModel.startFileScanning();

+ 2 - 2
app/src/main/java/com/datarecovery/master/module/homepage/HomePageViewModel.java

@@ -74,11 +74,11 @@ public class HomePageViewModel extends BaseViewModel {
     }
     }
 
 
     public void onWxMessageRecoveryClick() {
     public void onWxMessageRecoveryClick() {
-        isHaveAuths(MemberType.APP_WX_MESSAGE_RECOVER, () -> WeChatRecoverActivity.start(ActivityUtil.getTopActivity()));
+        isHaveAuths(MemberType.APP_WX_MESSAGE_RECOVER, () -> WeChatRecoverActivity.start(ActivityUtil.getTopActivity(), MemberType.APP_WX_MESSAGE_RECOVER));
     }
     }
 
 
     public void onWxFriendRecoveryClick() {
     public void onWxFriendRecoveryClick() {
-        isHaveAuths(MemberType.APP_WX_FRIEND_RECOVER, () -> WeChatRecoverActivity.start(ActivityUtil.getTopActivity()));
+        isHaveAuths(MemberType.APP_WX_FRIEND_RECOVER, () -> WeChatRecoverActivity.start(ActivityUtil.getTopActivity(), MemberType.APP_WX_FRIEND_RECOVER));
     }
     }
 
 
     public void onImgRecoveryClick() {
     public void onImgRecoveryClick() {

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverActivity.java

@@ -83,7 +83,7 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
     }
     }
 
 
     private void initPermission() {
     private void initPermission() {
-        new FilePermissionHelper().requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+        new FilePermissionHelper().requestDataFilePermission(this, (imageRecoverViewModel.getType() == Type.RECOVER) ? "hf11001" : "hf11013", new FilePermissionHelper.NextStepCallback() {
             @Override
             @Override
             public void onNextStep() {
             public void onNextStep() {
                 imageRecoverViewModel.startImageScanning();
                 imageRecoverViewModel.startImageScanning();

+ 8 - 1
app/src/main/java/com/datarecovery/master/module/login/LoginActivity.java

@@ -22,14 +22,16 @@ import dagger.hilt.android.AndroidEntryPoint;
 public class LoginActivity extends BaseActivity<ActivityLoginBinding> {
 public class LoginActivity extends BaseActivity<ActivityLoginBinding> {
 
 
 
 
+    private static final String REPORT_ID = "reportId";
     private LoginViewModel loginViewModel;
     private LoginViewModel loginViewModel;
 
 
 
 
-    public static void start(Context context) {
+    public static void start(Context context, String reportId) {
         Intent intent = new Intent(context, LoginActivity.class);
         Intent intent = new Intent(context, LoginActivity.class);
         if (!(context instanceof Activity)) {
         if (!(context instanceof Activity)) {
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         }
         }
+        intent.putExtra(REPORT_ID, reportId);
         context.startActivity(intent);
         context.startActivity(intent);
     }
     }
 
 
@@ -37,10 +39,15 @@ public class LoginActivity extends BaseActivity<ActivityLoginBinding> {
     @Override
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
+        initData();
         initView();
         initView();
         initObserver();
         initObserver();
     }
     }
 
 
+    private void initData() {
+        loginViewModel.setReportId(getIntent().getStringExtra(REPORT_ID));
+    }
+
     private void initView() {
     private void initView() {
         String agreeText = getString(R.string.login_agree_text);
         String agreeText = getString(R.string.login_agree_text);
         String userTermsText = getString(R.string.login_agree_user_terms_text);
         String userTermsText = getString(R.string.login_agree_user_terms_text);

+ 33 - 5
app/src/main/java/com/datarecovery/master/module/login/LoginViewModel.java

@@ -1,8 +1,7 @@
 package com.datarecovery.master.module.login;
 package com.datarecovery.master.module.login;
 
 
-import android.content.Context;
+import android.accounts.NetworkErrorException;
 import android.text.TextUtils;
 import android.text.TextUtils;
-import android.view.View;
 
 
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.LiveData;
@@ -11,12 +10,13 @@ import androidx.lifecycle.MutableLiveData;
 import com.atmob.app.lib.base.BaseViewModel;
 import com.atmob.app.lib.base.BaseViewModel;
 import com.atmob.app.lib.handler.RxHttpHandler;
 import com.atmob.app.lib.handler.RxHttpHandler;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
-import com.atmob.common.runtime.ContextUtil;
 import com.datarecovery.master.R;
 import com.datarecovery.master.R;
 import com.datarecovery.master.data.consts.ErrorCode;
 import com.datarecovery.master.data.consts.ErrorCode;
+import com.datarecovery.master.data.consts.EventId;
 import com.datarecovery.master.data.repositories.AccountRepository;
 import com.datarecovery.master.data.repositories.AccountRepository;
+import com.datarecovery.master.handler.EventHelper;
 import com.datarecovery.master.utils.BoxingUtil;
 import com.datarecovery.master.utils.BoxingUtil;
-import com.datarecovery.master.utils.SpannableUtil;
+import com.datarecovery.master.utils.Maps;
 import com.datarecovery.master.utils.ToastUtil;
 import com.datarecovery.master.utils.ToastUtil;
 
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
@@ -44,6 +44,7 @@ public class LoginViewModel extends BaseViewModel {
     private final SingleLiveEvent<?> finishEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> finishEvent = new SingleLiveEvent<>();
     private final AccountRepository accountRepository;
     private final AccountRepository accountRepository;
     private Disposable getCodeCountdownDisposable;
     private Disposable getCodeCountdownDisposable;
+    private String reportId;
 
 
     @Inject
     @Inject
     public LoginViewModel(AccountRepository accountRepository) {
     public LoginViewModel(AccountRepository accountRepository) {
@@ -156,10 +157,19 @@ public class LoginViewModel extends BaseViewModel {
     }
     }
 
 
     public void onLoginClick() {
     public void onLoginClick() {
-        if (!isCanLogin(phoneNum.getValue(), verificationCode.getValue())) {
+        EventHelper.report(EventId.hf1000302);
+        String phoneNumText = phoneNum.getValue();
+        if (!isPhone(phoneNumText)) {
+            ToastUtil.show(R.string.login_phone_num_11, ToastUtil.LENGTH_SHORT);
+            return;
+        }
+        String code = verificationCode.getValue();
+        if (TextUtils.isEmpty(code)) {
+            ToastUtil.show(R.string.login_code_hint, ToastUtil.LENGTH_SHORT);
             return;
             return;
         }
         }
         if (!BoxingUtil.boxing(isCheckedAgreement.getValue())) {
         if (!BoxingUtil.boxing(isCheckedAgreement.getValue())) {
+            EventHelper.report(EventId.hf1000304, Maps.asMap(EventId.EVENT_ID, "hf11019"));
             ToastUtil.show(R.string.login_please_agree, ToastUtil.LENGTH_SHORT);
             ToastUtil.show(R.string.login_please_agree, ToastUtil.LENGTH_SHORT);
             return;
             return;
         }
         }
@@ -176,24 +186,34 @@ public class LoginViewModel extends BaseViewModel {
                         showLoading.setValue(false);
                         showLoading.setValue(false);
                         ToastUtil.show(R.string.login_success, ToastUtil.LENGTH_SHORT);
                         ToastUtil.show(R.string.login_success, ToastUtil.LENGTH_SHORT);
                         finishEvent.call();
                         finishEvent.call();
+                        EventHelper.report(EventId.hf1000303);
                     }
                     }
 
 
                     @Override
                     @Override
                     public void onError(@NonNull Throwable e) {
                     public void onError(@NonNull Throwable e) {
                         showLoading.setValue(false);
                         showLoading.setValue(false);
                         if (e instanceof AccountRepository.LoginTooOftenException) {
                         if (e instanceof AccountRepository.LoginTooOftenException) {
+                            EventHelper.report(EventId.hf1000304, Maps.asMap(EventId.EVENT_ID, "hf11022"));
                             ToastUtil.show(R.string.login_too_often_toast, ToastUtil.LENGTH_SHORT);
                             ToastUtil.show(R.string.login_too_often_toast, ToastUtil.LENGTH_SHORT);
                             return;
                             return;
                         }
                         }
+                        if (e instanceof NetworkErrorException) {
+                            EventHelper.report(EventId.hf1000304, Maps.asMap(EventId.EVENT_ID, "hf11019"));
+                            ToastUtil.show(R.string.net_error, ToastUtil.LENGTH_SHORT);
+                            return;
+                        }
                         RxHttpHandler.ServerErrorException serverErrorException
                         RxHttpHandler.ServerErrorException serverErrorException
                                 = e instanceof RxHttpHandler.ServerErrorException ? ((RxHttpHandler.ServerErrorException) e) : null;
                                 = e instanceof RxHttpHandler.ServerErrorException ? ((RxHttpHandler.ServerErrorException) e) : null;
                         if (serverErrorException != null) {
                         if (serverErrorException != null) {
                             if (serverErrorException.getCode() == ErrorCode.ERROR_CODE_VERIFICATION_CODE_ERROR) {
                             if (serverErrorException.getCode() == ErrorCode.ERROR_CODE_VERIFICATION_CODE_ERROR) {
+                                EventHelper.report(EventId.hf1000304, Maps.asMap(EventId.EVENT_ID, "hf11021"));
                                 ToastUtil.show(R.string.login_verification_code_error_toast, ToastUtil.LENGTH_SHORT);
                                 ToastUtil.show(R.string.login_verification_code_error_toast, ToastUtil.LENGTH_SHORT);
                             } else {
                             } else {
+                                EventHelper.report(EventId.hf1000304, Maps.asMap(EventId.EVENT_ID, "hf11022"));
                                 ToastUtil.show(R.string.login_failed_toast, ToastUtil.LENGTH_SHORT);
                                 ToastUtil.show(R.string.login_failed_toast, ToastUtil.LENGTH_SHORT);
                             }
                             }
                         } else {
                         } else {
+                            EventHelper.report(EventId.hf1000304, Maps.asMap(EventId.EVENT_ID, "hf11022"));
                             ToastUtil.show(R.string.login_failed_toast, ToastUtil.LENGTH_SHORT);
                             ToastUtil.show(R.string.login_failed_toast, ToastUtil.LENGTH_SHORT);
                         }
                         }
                     }
                     }
@@ -217,4 +237,12 @@ public class LoginViewModel extends BaseViewModel {
         Matcher matcher = phonePattern.matcher(phoneNumText);
         Matcher matcher = phonePattern.matcher(phoneNumText);
         return matcher.matches();
         return matcher.matches();
     }
     }
+
+    public void setReportId(String reportId) {
+        if (!TextUtils.isEmpty(this.reportId)) {
+            return;
+        }
+        this.reportId = reportId;
+        EventHelper.report(EventId.hf1000301, Maps.asMap(EventId.EVENT_ID, reportId));
+    }
 }
 }

+ 8 - 0
app/src/main/java/com/datarecovery/master/module/main/MainActivity.java

@@ -23,6 +23,8 @@ import dagger.hilt.android.AndroidEntryPoint;
 public class MainActivity extends BaseActivity<ActivityMainBinding> {
 public class MainActivity extends BaseActivity<ActivityMainBinding> {
 
 
 
 
+    private MainViewModel mainViewModel;
+
     private TabLayoutMediator tabLayoutMediator;
     private TabLayoutMediator tabLayoutMediator;
     private MainPagerAdapter mainPagerAdapter;
     private MainPagerAdapter mainPagerAdapter;
     private long mExitTime;
     private long mExitTime;
@@ -115,6 +117,12 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
     }
     }
 
 
     @Override
     @Override
+    protected void initViewModel() {
+        super.initViewModel();
+        mainViewModel = getViewModelProvider().get(MainViewModel.class);
+    }
+
+    @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
         if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
             exit();
             exit();

+ 20 - 0
app/src/main/java/com/datarecovery/master/module/main/MainViewModel.java

@@ -0,0 +1,20 @@
+package com.datarecovery.master.module.main;
+
+import com.atmob.app.lib.base.BaseViewModel;
+import com.datarecovery.master.data.repositories.MemberRepository;
+import com.datarecovery.master.utils.OrderReportHelper;
+import com.google.gson.Gson;
+
+import javax.inject.Inject;
+
+import dagger.hilt.android.lifecycle.HiltViewModel;
+
+@HiltViewModel
+public class MainViewModel extends BaseViewModel {
+
+
+    @Inject
+    public MainViewModel(Gson gson, MemberRepository memberRepository) {
+        OrderReportHelper.init(gson, memberRepository);
+    }
+}

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/member/GoodsItemAdapter.java

@@ -44,7 +44,7 @@ public class GoodsItemAdapter extends RecyclerView.Adapter<GoodsItemAdapter.View
             public boolean areContentsTheSame(@NonNull MemberGoodsBean oldItem, @NonNull MemberGoodsBean newItem) {
             public boolean areContentsTheSame(@NonNull MemberGoodsBean oldItem, @NonNull MemberGoodsBean newItem) {
                 return Objects.equals(oldItem.getName(), newItem.getName())
                 return Objects.equals(oldItem.getName(), newItem.getName())
                         && Objects.equals(oldItem.getOriginalAmount(), newItem.getOriginalAmount())
                         && Objects.equals(oldItem.getOriginalAmount(), newItem.getOriginalAmount())
-                        && Objects.equals(oldItem.getAmount(), newItem.getAmount())
+                        && Objects.equals(oldItem.getRMBAmount(), newItem.getRMBAmount())
                         && Objects.equals(oldItem.getDescription(), newItem.getDescription());
                         && Objects.equals(oldItem.getDescription(), newItem.getDescription());
             }
             }
         });
         });

+ 3 - 2
app/src/main/java/com/datarecovery/master/module/member/MemberActivity.java

@@ -13,7 +13,6 @@ import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.LinearLayoutManager;
 
 
 import com.atmob.app.lib.base.BaseActivity;
 import com.atmob.app.lib.base.BaseActivity;
-import com.atmob.common.logging.AtmobLog;
 import com.atmob.common.ui.SizeUtil;
 import com.atmob.common.ui.SizeUtil;
 import com.datarecovery.master.databinding.ActivityMemberBinding;
 import com.datarecovery.master.databinding.ActivityMemberBinding;
 import com.datarecovery.master.dialog.AlipayQrCodeDialog;
 import com.datarecovery.master.dialog.AlipayQrCodeDialog;
@@ -147,8 +146,10 @@ public class MemberActivity extends BaseActivity<ActivityMemberBinding> {
         finish();
         finish();
         switch (memberViewModel.getMemberType()) {
         switch (memberViewModel.getMemberType()) {
             case MemberType.APP_WX_MESSAGE_RECOVER:
             case MemberType.APP_WX_MESSAGE_RECOVER:
+                WeChatRecoverActivity.start(this, MemberType.APP_WX_MESSAGE_RECOVER);
+                break;
             case MemberType.APP_WX_FRIEND_RECOVER:
             case MemberType.APP_WX_FRIEND_RECOVER:
-                WeChatRecoverActivity.start(this);
+                WeChatRecoverActivity.start(this, MemberType.APP_WX_FRIEND_RECOVER);
                 break;
                 break;
             case MemberType.APP_IMAGE_RECOVER:
             case MemberType.APP_IMAGE_RECOVER:
                 ImageRecoverActivity.start(this, ImageRecoverActivity.Type.RECOVER);
                 ImageRecoverActivity.start(this, ImageRecoverActivity.Type.RECOVER);

+ 52 - 8
app/src/main/java/com/datarecovery/master/module/member/MemberViewModel.java

@@ -7,7 +7,6 @@ import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.MutableLiveData;
 
 
 import com.atmob.app.lib.base.BaseViewModel;
 import com.atmob.app.lib.base.BaseViewModel;
-import com.atmob.app.lib.handler.RxHttpHandler;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
 import com.atmob.common.runtime.ActivityUtil;
 import com.atmob.common.runtime.ActivityUtil;
 import com.atmob.common.runtime.ContextUtil;
 import com.atmob.common.runtime.ContextUtil;
@@ -17,13 +16,16 @@ import com.datarecovery.master.data.api.bean.PayOptionsBean;
 import com.datarecovery.master.data.api.bean.WechatPaymentSignBean;
 import com.datarecovery.master.data.api.bean.WechatPaymentSignBean;
 import com.datarecovery.master.data.api.response.MemberDetailResponse;
 import com.datarecovery.master.data.api.response.MemberDetailResponse;
 import com.datarecovery.master.data.api.response.MemberPayResponse;
 import com.datarecovery.master.data.api.response.MemberPayResponse;
+import com.datarecovery.master.data.consts.Constants;
 import com.datarecovery.master.data.repositories.AccountRepository;
 import com.datarecovery.master.data.repositories.AccountRepository;
 import com.datarecovery.master.data.repositories.MemberRepository;
 import com.datarecovery.master.data.repositories.MemberRepository;
+import com.datarecovery.master.handler.EventHelper;
 import com.datarecovery.master.module.login.LoginActivity;
 import com.datarecovery.master.module.login.LoginActivity;
 import com.datarecovery.master.module.member.bean.EvaluateBean;
 import com.datarecovery.master.module.member.bean.EvaluateBean;
 import com.datarecovery.master.module.member.bean.SuperScenesBean;
 import com.datarecovery.master.module.member.bean.SuperScenesBean;
-import com.datarecovery.master.module.wxrecover.WeChatRecoverActivity;
 import com.datarecovery.master.utils.BoxingUtil;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.OrderReportHelper;
+import com.datarecovery.master.utils.RxHttpHandler;
 import com.datarecovery.master.utils.ToastUtil;
 import com.datarecovery.master.utils.ToastUtil;
 import com.google.gson.Gson;
 import com.google.gson.Gson;
 
 
@@ -70,6 +72,8 @@ public class MemberViewModel extends BaseViewModel {
 
 
     private final SingleLiveEvent<Pair<String, String>> showWxQRPaymentEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<Pair<String, String>> showWxQRPaymentEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<Pair<String, String>> showAliQRPaymentEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<Pair<String, String>> showAliQRPaymentEvent = new SingleLiveEvent<>();
+
+    private final HashMap<String, MemberGoodsBean> orderIdItemMap = new HashMap<>();
     @MemberType
     @MemberType
     private String memberType;
     private String memberType;
 
 
@@ -291,6 +295,7 @@ public class MemberViewModel extends BaseViewModel {
             @Override
             @Override
             public void onSuccess(@NonNull MemberPayResponse memberPayResponse) {
             public void onSuccess(@NonNull MemberPayResponse memberPayResponse) {
                 showLoadingEvent.setValue(false);
                 showLoadingEvent.setValue(false);
+                orderIdItemMap.put(memberPayResponse.getOutTradeNo(), bean);
                 if (payPlatform == 1 && payMethod == 2) {
                 if (payPlatform == 1 && payMethod == 2) {
                     onWeChatPay(memberPayResponse.getWechatPayPrepayJson(), memberPayResponse.getOutTradeNo());
                     onWeChatPay(memberPayResponse.getWechatPayPrepayJson(), memberPayResponse.getOutTradeNo());
                 } else if (payPlatform == 4 && payMethod == 2) {
                 } else if (payPlatform == 4 && payMethod == 2) {
@@ -308,7 +313,12 @@ public class MemberViewModel extends BaseViewModel {
                 showLoadingEvent.setValue(false);
                 showLoadingEvent.setValue(false);
                 if (throwable instanceof RxHttpHandler.ServerErrorException) {
                 if (throwable instanceof RxHttpHandler.ServerErrorException) {
                     RxHttpHandler.ServerErrorException serverErrorException = (RxHttpHandler.ServerErrorException) throwable;
                     RxHttpHandler.ServerErrorException serverErrorException = (RxHttpHandler.ServerErrorException) throwable;
-                    ToastUtil.show(serverErrorException.getMsg(), ToastUtil.LENGTH_SHORT);
+                    if (serverErrorException.getCode() == Constants.ERROR_CODE_NO_LOGIN_ERROR) {
+                        ToastUtil.show(R.string.no_login, ToastUtil.LENGTH_SHORT);
+                        LoginActivity.start(ActivityUtil.getTopActivity(), getReportId());
+                    } else {
+                        ToastUtil.show(serverErrorException.getMsg(), ToastUtil.LENGTH_SHORT);
+                    }
                 } else {
                 } else {
                     ToastUtil.show(R.string.member_payment_failed, ToastUtil.LENGTH_SHORT);
                     ToastUtil.show(R.string.member_payment_failed, ToastUtil.LENGTH_SHORT);
                 }
                 }
@@ -316,6 +326,25 @@ public class MemberViewModel extends BaseViewModel {
         });
         });
     }
     }
 
 
+    public String getReportId() {
+        if (Objects.equals(memberType, MemberType.APP_WX_MESSAGE_RECOVER)) {
+            return "hf11011";
+        } else if (Objects.equals(memberType, MemberType.APP_WX_FRIEND_RECOVER)) {
+            return "hf11009";
+        } else if (Objects.equals(memberType, MemberType.APP_IMAGE_RECOVER)) {
+            return "hf11001";
+        } else if (Objects.equals(memberType, MemberType.APP_FILE_RECOVER)) {
+            return "hf11003";
+        } else if (Objects.equals(memberType, MemberType.APP_VIDEO_RECOVER)) {
+            return "hf11005";
+        } else if (Objects.equals(memberType, MemberType.APP_AUDIO_RECOVER)) {
+            return "hf11007";
+        } else if (Objects.equals(memberType, MemberType.APP_IMAGE_CLEAN)) {
+            return "hf11013";
+        }
+        return null;
+    }
+
     private void onAliPayScan(String s, String orderId) {
     private void onAliPayScan(String s, String orderId) {
         showAliQRPaymentEvent.setValue(new Pair<>(s, orderId));
         showAliQRPaymentEvent.setValue(new Pair<>(s, orderId));
     }
     }
@@ -323,7 +352,7 @@ public class MemberViewModel extends BaseViewModel {
     private void onAliPay(String s, String orderId) {
     private void onAliPay(String s, String orderId) {
         AlipayInfo alipayInfo = new AlipayInfo();
         AlipayInfo alipayInfo = new AlipayInfo();
         alipayInfo.setContent(s);
         alipayInfo.setContent(s);
-        requestSdkPay(alipayInfo, orderId);
+        requestSdkPay(alipayInfo, orderId, Constants.PAYMENT_WAY_ALIPAY);
     }
     }
 
 
     private void onWeChatScanPay(String s, String orderId) {
     private void onWeChatScanPay(String s, String orderId) {
@@ -341,13 +370,13 @@ public class MemberViewModel extends BaseViewModel {
             wXpayInfo.setNoncestr(wechatPaymentSignBean.getRandomStr());
             wXpayInfo.setNoncestr(wechatPaymentSignBean.getRandomStr());
             wXpayInfo.setTimestamp(wechatPaymentSignBean.getTimeStamp());
             wXpayInfo.setTimestamp(wechatPaymentSignBean.getTimeStamp());
             wXpayInfo.setSign(wechatPaymentSignBean.getSign());
             wXpayInfo.setSign(wechatPaymentSignBean.getSign());
-            requestSdkPay(wXpayInfo, orderId);
+            requestSdkPay(wXpayInfo, orderId, Constants.PAYMENT_WAY_WECHAT);
         } catch (Exception e) {
         } catch (Exception e) {
             e.printStackTrace();
             e.printStackTrace();
         }
         }
     }
     }
 
 
-    private void requestSdkPay(Object payInfo, String orderId) {
+    private void requestSdkPay(Object payInfo, String orderId, int payWay) {
         AgilePay.pay(payInfo, ActivityUtil.getTopActivity(), new AgilePayState() {
         AgilePay.pay(payInfo, ActivityUtil.getTopActivity(), new AgilePayState() {
             @Override
             @Override
             public void error(int errno, String error) {
             public void error(int errno, String error) {
@@ -369,7 +398,11 @@ public class MemberViewModel extends BaseViewModel {
 
 
             @Override
             @Override
             public void paySuccess(String result) {
             public void paySuccess(String result) {
-                queryOrderStatus(orderId, true);
+                MemberGoodsBean bean = orderIdItemMap.get(orderId);
+                if (bean != null) {
+                    EventHelper.reportPay(bean.getAmount(), orderId, payWay, bean.getName());
+                }
+                queryOrderStatus(orderId, payWay, true, false);
             }
             }
 
 
             @Override
             @Override
@@ -379,7 +412,11 @@ public class MemberViewModel extends BaseViewModel {
         });
         });
     }
     }
 
 
-    public @NonNull Disposable queryOrderStatus(String orderId, boolean showLoading) {
+    public @NonNull Disposable queryOrderStatus(String orderId, int payWay, boolean showLoading, boolean isReportPay) {
+        MemberGoodsBean memberBean = orderIdItemMap.get(orderId);
+        if (memberBean != null && isReportPay) {
+            OrderReportHelper.recordOrderId(memberBean.getAmount(), orderId, payWay, memberBean.getName());
+        }
         return memberRepository.getPayStatus(orderId)
         return memberRepository.getPayStatus(orderId)
                 .doOnSubscribe(disposable -> {
                 .doOnSubscribe(disposable -> {
                     if (showLoading) {
                     if (showLoading) {
@@ -387,6 +424,13 @@ public class MemberViewModel extends BaseViewModel {
                         addDisposable(RxJavaUtil.timer(10, TimeUnit.SECONDS, () -> showLoadingEvent.setValue(false)));
                         addDisposable(RxJavaUtil.timer(10, TimeUnit.SECONDS, () -> showLoadingEvent.setValue(false)));
                     }
                     }
                 })
                 })
+                .doOnSuccess(success -> {
+                    if (isReportPay) {
+                        if (BoxingUtil.boxing(success) && memberBean != null) {
+                            EventHelper.reportPay(memberBean.getAmount(), orderId, payWay, memberBean.getName());
+                        }
+                    }
+                })
                 .subscribe(aBoolean -> {
                 .subscribe(aBoolean -> {
                     showLoadingEvent.setValue(false);
                     showLoadingEvent.setValue(false);
                     if (BoxingUtil.boxing(aBoolean)) {
                     if (BoxingUtil.boxing(aBoolean)) {

+ 41 - 0
app/src/main/java/com/datarecovery/master/module/member/bean/PayInfo.java

@@ -0,0 +1,41 @@
+package com.datarecovery.master.module.member.bean;
+
+public class PayInfo {
+
+    private int payAmount;
+    private String orderId;
+    private int payWay;
+    private String product;
+
+    private final long payTime;
+
+    public PayInfo(int payAmount, String orderId, int payWay, String product) {
+        this.payAmount = payAmount;
+        this.orderId = orderId;
+        this.product = product;
+        this.payWay = payWay;
+        payTime = System.currentTimeMillis();
+    }
+
+    public long getPayTime() {
+        return payTime;
+    }
+
+    public int getPayAmount() {
+        return payAmount;
+    }
+
+    public String getOrderId() {
+        return orderId;
+    }
+
+    public String getProduct() {
+        return product;
+    }
+
+    public int getPayWay() {
+        return payWay;
+    }
+
+
+}

+ 4 - 4
app/src/main/java/com/datarecovery/master/module/mine/MineViewModel.java

@@ -71,7 +71,7 @@ public class MineViewModel extends BaseViewModel {
         if (BoxingUtil.boxing(accountRepository.getIsLogin().getValue())) {
         if (BoxingUtil.boxing(accountRepository.getIsLogin().getValue())) {
             return;
             return;
         }
         }
-        LoginActivity.start(ActivityUtil.getTopActivity());
+        LoginActivity.start(ActivityUtil.getTopActivity(), "hf11018");
     }
     }
 
 
     public void onAboutClick() {
     public void onAboutClick() {
@@ -83,7 +83,7 @@ public class MineViewModel extends BaseViewModel {
     }
     }
 
 
     public void onAccountExit() {
     public void onAccountExit() {
-        accountRepository.logout();
+        accountRepository.requestUserLogout();
     }
     }
 
 
     public void onLogoutClick() {
     public void onLogoutClick() {
@@ -91,7 +91,7 @@ public class MineViewModel extends BaseViewModel {
     }
     }
 
 
     public void onAccountLogout() {
     public void onAccountLogout() {
-        accountRepository.logout();
+
     }
     }
 
 
     public void onFeedbackClick() {
     public void onFeedbackClick() {
@@ -100,7 +100,7 @@ public class MineViewModel extends BaseViewModel {
 
 
     public void onMemberClick() {
     public void onMemberClick() {
         //指定跳转至微信消息恢复
         //指定跳转至微信消息恢复
-        isHaveAuths(MemberType.APP_WX_MESSAGE_RECOVER, () -> WeChatRecoverActivity.start(ActivityUtil.getTopActivity()));
+        isHaveAuths(MemberType.APP_WX_MESSAGE_RECOVER, () -> WeChatRecoverActivity.start(ActivityUtil.getTopActivity(), MemberType.APP_WX_MESSAGE_RECOVER));
     }
     }
 
 
     public void isHaveAuths(@MemberType String type, HomePageViewModel.NextStepCallback stepCallback) {
     public void isHaveAuths(@MemberType String type, HomePageViewModel.NextStepCallback stepCallback) {

+ 5 - 0
app/src/main/java/com/datarecovery/master/module/order/OrderItemAdapter.java

@@ -97,6 +97,11 @@ public class OrderItemAdapter extends RecyclerView.Adapter<OrderItemAdapter.View
                 ClipboardUtil.copy(orderBean.getTutorialLink());
                 ClipboardUtil.copy(orderBean.getTutorialLink());
                 ToastUtil.show(R.string.copy_success, ToastUtil.LENGTH_SHORT);
                 ToastUtil.show(R.string.copy_success, ToastUtil.LENGTH_SHORT);
             });
             });
+            binding.tvAuthCodeCopy.setOnClickListener(v -> {
+                OrderBean orderBean = binding.getOrderBean();
+                ClipboardUtil.copy(orderBean.getAuthCode());
+                ToastUtil.show(R.string.copy_success, ToastUtil.LENGTH_SHORT);
+            });
         }
         }
 
 
         public void bind(OrderBean orderBean) {
         public void bind(OrderBean orderBean) {

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/splash/SplashActivity.java

@@ -20,7 +20,7 @@ import com.gyf.immersionbar.ImmersionBar;
 public class SplashActivity extends BaseActivity<ActivitySplashBinding> {
 public class SplashActivity extends BaseActivity<ActivitySplashBinding> {
 
 
     private AgreementDialog agreementDialog;
     private AgreementDialog agreementDialog;
-    private final int delayMillis = 1000;
+    private final int delayMillis = 2000;
 
 
     @Override
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
     protected void onCreate(@Nullable Bundle savedInstanceState) {

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/videorecover/VideoRecoverActivity.java

@@ -54,7 +54,7 @@ public class VideoRecoverActivity extends BaseActivity<ActivityVideoRecoverBindi
     }
     }
 
 
     private void initPermission() {
     private void initPermission() {
-        new FilePermissionHelper().requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+        new FilePermissionHelper().requestDataFilePermission(this, "hf11005", new FilePermissionHelper.NextStepCallback() {
             @Override
             @Override
             public void onNextStep() {
             public void onNextStep() {
                 videoRecoverViewModel.startVideoScanning();
                 videoRecoverViewModel.startVideoScanning();

+ 44 - 1
app/src/main/java/com/datarecovery/master/module/wxrecover/WeChatRecoverActivity.java

@@ -4,12 +4,19 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Bundle;
+import android.text.TextUtils;
 
 
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.Nullable;
 
 
 import com.atmob.app.lib.base.BaseActivity;
 import com.atmob.app.lib.base.BaseActivity;
+import com.datarecovery.master.R;
+import com.datarecovery.master.data.repositories.AccountRepository;
 import com.datarecovery.master.databinding.ActivityWxRecoverBinding;
 import com.datarecovery.master.databinding.ActivityWxRecoverBinding;
+import com.datarecovery.master.dialog.PermissionDialog;
+import com.datarecovery.master.module.login.LoginActivity;
+import com.datarecovery.master.module.member.MemberType;
+import com.datarecovery.master.utils.FilePermissionHelper;
 import com.gyf.immersionbar.ImmersionBar;
 import com.gyf.immersionbar.ImmersionBar;
 
 
 import dagger.hilt.android.AndroidEntryPoint;
 import dagger.hilt.android.AndroidEntryPoint;
@@ -19,28 +26,55 @@ public class WeChatRecoverActivity extends BaseActivity<ActivityWxRecoverBinding
 
 
 
 
     private WeChatViewModel weChatViewModel;
     private WeChatViewModel weChatViewModel;
+    private PermissionDialog loginDialog;
 
 
-    public static void start(Context context) {
+
+    public static void start(Context context, @MemberType String type) {
         Intent intent = new Intent(context, WeChatRecoverActivity.class);
         Intent intent = new Intent(context, WeChatRecoverActivity.class);
         if (!(context instanceof Activity)) {
         if (!(context instanceof Activity)) {
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         }
         }
+        intent.putExtra("TYPE", type);
         context.startActivity(intent);
         context.startActivity(intent);
     }
     }
 
 
     @Override
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
+        initData();
         initView();
         initView();
         initObserver();
         initObserver();
     }
     }
 
 
+    private void initData() {
+        weChatViewModel.setType(getIntent().getStringExtra("TYPE"));
+    }
+
     private void initView() {
     private void initView() {
 
 
     }
     }
 
 
+    private void showLoginDialog() {
+        loginDialog = new PermissionDialog(this);
+        loginDialog.setDialogContent(R.string.dialog_no_login)
+                .setDialogTitle(R.string.dialog_no_login_title)
+                .setOnDialogClickListener(new PermissionDialog.OnDialogClickListener() {
+                    @Override
+                    public void onClickSure() {
+                        LoginActivity.start(WeChatRecoverActivity.this, weChatViewModel.getReportId());
+                    }
+
+                    @Override
+                    public void onClickCancel() {
+                        finish();
+                    }
+                });
+        loginDialog.show();
+    }
+
     private void initObserver() {
     private void initObserver() {
         weChatViewModel.getFinishEvent().observe(this, o -> finish());
         weChatViewModel.getFinishEvent().observe(this, o -> finish());
+        weChatViewModel.getShowLoginEvent().observe(this, o -> showLoginDialog());
     }
     }
 
 
     @Override
     @Override
@@ -59,4 +93,13 @@ public class WeChatRecoverActivity extends BaseActivity<ActivityWxRecoverBinding
     protected void configImmersion(@NonNull ImmersionBar immersionBar) {
     protected void configImmersion(@NonNull ImmersionBar immersionBar) {
         immersionBar.statusBarDarkFont(true);
         immersionBar.statusBarDarkFont(true);
     }
     }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (loginDialog != null && loginDialog.isShowing() && !TextUtils.isEmpty(AccountRepository.token)) {
+            weChatViewModel.findOrder();
+            loginDialog.dismiss();
+        }
+    }
 }
 }

+ 32 - 1
app/src/main/java/com/datarecovery/master/module/wxrecover/WeChatViewModel.java

@@ -1,5 +1,7 @@
 package com.datarecovery.master.module.wxrecover;
 package com.datarecovery.master.module.wxrecover;
 
 
+import android.text.TextUtils;
+
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.MutableLiveData;
 
 
@@ -7,11 +9,14 @@ import com.atmob.app.lib.base.BaseViewModel;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
 import com.datarecovery.master.R;
 import com.datarecovery.master.R;
 import com.datarecovery.master.data.api.response.FindOrderResponse;
 import com.datarecovery.master.data.api.response.FindOrderResponse;
+import com.datarecovery.master.data.repositories.AccountRepository;
 import com.datarecovery.master.data.repositories.PayRepository;
 import com.datarecovery.master.data.repositories.PayRepository;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.utils.ClipboardUtil;
 import com.datarecovery.master.utils.ClipboardUtil;
 import com.datarecovery.master.utils.ToastUtil;
 import com.datarecovery.master.utils.ToastUtil;
 
 
+import java.util.Objects;
+
 import javax.inject.Inject;
 import javax.inject.Inject;
 
 
 import atmob.reactivex.rxjava3.annotations.NonNull;
 import atmob.reactivex.rxjava3.annotations.NonNull;
@@ -25,14 +30,24 @@ public class WeChatViewModel extends BaseViewModel {
 
 
 
 
     private final SingleLiveEvent<?> finishEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> finishEvent = new SingleLiveEvent<>();
+    private final SingleLiveEvent<?> showLoginEvent = new SingleLiveEvent<>();
 
 
     private final MutableLiveData<FindOrderResponse> findOrderDetail = new MutableLiveData<>();
     private final MutableLiveData<FindOrderResponse> findOrderDetail = new MutableLiveData<>();
     private final PayRepository payRepository;
     private final PayRepository payRepository;
+    private String type;
 
 
     @Inject
     @Inject
     public WeChatViewModel(PayRepository payRepository) {
     public WeChatViewModel(PayRepository payRepository) {
         this.payRepository = payRepository;
         this.payRepository = payRepository;
-        findOrder();
+        if (TextUtils.isEmpty(AccountRepository.token)) {
+            showLoginEvent.call();
+        } else {
+            findOrder();
+        }
+    }
+
+    public LiveData<?> getShowLoginEvent() {
+        return showLoginEvent;
     }
     }
 
 
     public LiveData<FindOrderResponse> getFindOrderDetail() {
     public LiveData<FindOrderResponse> getFindOrderDetail() {
@@ -93,4 +108,20 @@ public class WeChatViewModel extends BaseViewModel {
         ClipboardUtil.copy(value.getAuthCode());
         ClipboardUtil.copy(value.getAuthCode());
         ToastUtil.show(R.string.copy_success, ToastUtil.LENGTH_SHORT);
         ToastUtil.show(R.string.copy_success, ToastUtil.LENGTH_SHORT);
     }
     }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getReportId() {
+        if (Objects.equals(type, MemberType.APP_WX_MESSAGE_RECOVER)) {
+            return "hf11011";
+        } else {
+            return "hf11009";
+        }
+    }
 }
 }

+ 2 - 2
app/src/main/java/com/datarecovery/master/utils/FilePermissionHelper.java

@@ -28,7 +28,7 @@ public class FilePermissionHelper {
 
 
     Disposable disposable;
     Disposable disposable;
 
 
-    public void requestDataFilePermission(ComponentActivity activity, NextStepCallback stepCallback) {
+    public void requestDataFilePermission(ComponentActivity activity, String reportId, NextStepCallback stepCallback) {
         Single.just(Build.VERSION.SDK_INT)
         Single.just(Build.VERSION.SDK_INT)
                 .flatMap(sdkInt -> {
                 .flatMap(sdkInt -> {
                     if (TextUtils.isEmpty(AccountRepository.token)) {
                     if (TextUtils.isEmpty(AccountRepository.token)) {
@@ -39,7 +39,7 @@ public class FilePermissionHelper {
                                     .setOnDialogClickListener(new PermissionDialog.OnDialogClickListener() {
                                     .setOnDialogClickListener(new PermissionDialog.OnDialogClickListener() {
                                         @Override
                                         @Override
                                         public void onClickSure() {
                                         public void onClickSure() {
-                                            LoginActivity.start(activity);
+                                            LoginActivity.start(activity, reportId);
                                             activity.getLifecycle().addObserver(new LifecycleEventObserver() {
                                             activity.getLifecycle().addObserver(new LifecycleEventObserver() {
                                                 @Override
                                                 @Override
                                                 public void onStateChanged(@androidx.annotation.NonNull LifecycleOwner lifecycleOwner, @androidx.annotation.NonNull Lifecycle.Event event) {
                                                 public void onStateChanged(@androidx.annotation.NonNull LifecycleOwner lifecycleOwner, @androidx.annotation.NonNull Lifecycle.Event event) {

+ 12 - 0
app/src/main/java/com/datarecovery/master/utils/Maps.java

@@ -0,0 +1,12 @@
+package com.datarecovery.master.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Maps {
+    public static <K, V> Map<K, V> asMap(K key, V value) {
+        HashMap<K, V> kvHashMap = new HashMap<>(1);
+        kvHashMap.put(key, value);
+        return kvHashMap;
+    }
+}

+ 130 - 0
app/src/main/java/com/datarecovery/master/utils/OrderReportHelper.java

@@ -0,0 +1,130 @@
+package com.datarecovery.master.utils;
+
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.atmob.common.data.KVUtils;
+import com.datarecovery.master.data.repositories.MemberRepository;
+import com.datarecovery.master.handler.EventHelper;
+import com.datarecovery.master.module.member.bean.PayInfo;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import java.util.HashMap;
+
+import javax.inject.Singleton;
+
+import atmob.reactivex.rxjava3.annotations.NonNull;
+import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.disposables.Disposable;
+
+
+public class OrderReportHelper {
+
+    private static final String TAG = "OrderReportHelper";
+
+    private static HashMap<String, PayInfo> notReportedPayMap;
+
+    private static final String RECORD_PAY_ORDER_ID_LIST = "record_pay_order_id_list";
+
+    private static Gson gson;
+    private static MemberRepository memberRepository;
+
+    private static final long MAX_QUERY_TIME = 60 * 1000L;
+
+    private OrderReportHelper() {
+
+    }
+
+    @Singleton
+    public static void init(Gson gson, MemberRepository memberRepository) {
+        OrderReportHelper.gson = gson;
+        OrderReportHelper.memberRepository = memberRepository;
+        initMap();
+    }
+
+    private static void initMap() {
+        String payInfoString = KVUtils.getDefault().getString(RECORD_PAY_ORDER_ID_LIST, "");
+        if (TextUtils.isEmpty(payInfoString)) {
+            notReportedPayMap = new HashMap<>();
+        } else {
+            notReportedPayMap = toGsonMap(payInfoString);
+        }
+        queryOrderStatus();
+    }
+
+    public static void queryOrderStatus() {
+        if (notReportedPayMap.size() == 0 || memberRepository == null) {
+            return;
+        }
+        for (String orderId : notReportedPayMap.keySet()) {
+            PayInfo payInfo = notReportedPayMap.get(orderId);
+            if (payInfo == null) {
+                continue;
+            }
+            if (System.currentTimeMillis() - payInfo.getPayTime() > MAX_QUERY_TIME) {
+                removeOderId(orderId);
+                continue;
+            }
+            memberRepository.getPayStatus(orderId).subscribe(new SingleObserver<Boolean>() {
+                @Override
+                public void onSubscribe(@NonNull Disposable d) {
+
+                }
+
+                @Override
+                public void onSuccess(@NonNull Boolean paySuccess) {
+                    Log.d(TAG, "onSuccess: " + paySuccess + "--orderId:" + orderId);
+                    if (BoxingUtil.boxing(paySuccess)) {
+//                        EventHelper.reportPay(payInfo.getPayAmount(), payInfo.getOrderId(), payInfo.getPayWay(), payInfo.getProduct());
+                    }
+                }
+
+                @Override
+                public void onError(@NonNull Throwable e) {
+
+                }
+
+
+            });
+        }
+
+    }
+
+    private static HashMap<String, PayInfo> toGsonMap(String jsonStr) {
+        HashMap<String, PayInfo> res = null;
+        try {
+            res = gson.fromJson(jsonStr, new TypeToken<HashMap<String, PayInfo>>() {
+            }.getType());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (res == null) {
+            res = new HashMap<>();
+        }
+        return res;
+    }
+
+
+    public static void recordOrderId(int payAmount, String orderId, int payWay, String product) {
+        if (notReportedPayMap.containsKey(orderId)) {
+            return;
+        }
+        notReportedPayMap.put(orderId, new PayInfo(payAmount, orderId, payWay, product));
+        KVUtils.getDefault().putString(RECORD_PAY_ORDER_ID_LIST, gson.toJson(notReportedPayMap));
+    }
+
+    public static void removeOderId(String orderId) {
+        if (TextUtils.isEmpty(orderId)) {
+            return;
+        }
+        boolean contains = notReportedPayMap.containsKey(orderId);
+        if (contains) {
+            notReportedPayMap.remove(orderId);
+            KVUtils.getDefault().putString(RECORD_PAY_ORDER_ID_LIST, gson.toJson(notReportedPayMap));
+        }
+    }
+
+
+}

+ 117 - 0
app/src/main/java/com/datarecovery/master/utils/RxHttpHandler.java

@@ -0,0 +1,117 @@
+package com.datarecovery.master.utils;
+
+
+import android.app.Application;
+import android.os.Handler;
+import android.os.Looper;
+
+import androidx.annotation.NonNull;
+
+import com.atmob.app.lib.base.BaseResponse;
+import com.atmob.common.runtime.ContextUtil;
+import com.atmob.common.runtime.ProcessUtil;
+import com.datarecovery.master.data.consts.Constants;
+import com.datarecovery.master.data.repositories.AccountRepository;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+import atmob.reactivex.rxjava3.core.SingleTransformer;
+import dagger.hilt.EntryPoint;
+import dagger.hilt.InstallIn;
+import dagger.hilt.android.EntryPointAccessors;
+import dagger.hilt.components.SingletonComponent;
+
+/**
+ * 处理RxJava封装的http响应结果, 后续可以根据某些通用code或者exception在此处聚合处理
+ */
+public class RxHttpHandler {
+
+    private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
+
+    public static <T> SingleTransformer<BaseResponse<T>, T> handle(boolean allowEmptyData) {
+        return upstream -> upstream
+                .compose(handleInternal(allowEmptyData));
+    }
+
+    private static <T> SingleTransformer<BaseResponse<T>, T> handleInternal(boolean allowEmptyData) {
+        return upstream -> upstream.map(
+                        response -> {
+                            if (response == null) {
+                                throw new Exception("response is null");
+                            }
+                            int code = response.getCode();
+                            T data = response.getData();
+                            if (code == 0) {
+                                if (data != null || allowEmptyData) {
+                                    return data == null ? createT(response) : data;
+                                } else {
+                                    throw new Exception("data is null");
+                                }
+                            } else {
+                                throw new ServerErrorException(code, response.getMsg());
+                            }
+                        })
+                .doOnSuccess(RxHttpHandler::doOnSuccess)
+                .doOnError(RxHttpHandler::doOnResponseError);
+    }
+
+    private static <T> T createT(@NonNull BaseResponse<T> response) {
+        try {
+            Field data = response.getClass().getDeclaredField("data");
+            Class<?> type = data.getType();
+            Constructor<?> constructor = type.getConstructor();
+            Object o = constructor.newInstance();
+            return (T) o;
+        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
+                 InvocationTargetException | NoSuchFieldException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static <T> void doOnSuccess(T t) {
+        // TODO: 2022/5/25 请求成功的通用处理, 比如含有UserBean的Response, 发送刷新各界面用户信息的Event
+    }
+
+    public static void doOnResponseError(Throwable throwable) {
+        if (!ProcessUtil.isMainThread()) {
+            MAIN_HANDLER.post(() -> doOnResponseError(throwable));
+            return;
+        }
+        ServerErrorException serverErrorException = throwable instanceof ServerErrorException ? ((ServerErrorException) throwable) : null;
+        if (serverErrorException != null) {
+            if (serverErrorException.getCode() == Constants.ERROR_CODE_NO_LOGIN_ERROR) {
+                Application application = ContextUtil.getApplication();
+                EntryPointAccessors.fromApplication(application, RxHttpHandlerEntryPoint.class)
+                        .accountRepository()
+                        .logout();
+            }
+        }
+    }
+
+    public static class ServerErrorException extends Exception {
+        private final int code;
+        private final String msg;
+
+        public ServerErrorException(int code, String msg) {
+            this.code = code;
+            this.msg = msg;
+        }
+
+        public int getCode() {
+            return code;
+        }
+
+        public String getMsg() {
+            return msg;
+        }
+    }
+
+    @InstallIn(SingletonComponent.class)
+    @EntryPoint
+    interface RxHttpHandlerEntryPoint {
+        AccountRepository accountRepository();
+    }
+}

+ 6 - 1
app/src/main/res/layout/dialog_agreement.xml

@@ -13,6 +13,11 @@
             name="onAgreeClickListener"
             name="onAgreeClickListener"
             type="android.view.View.OnClickListener" />
             type="android.view.View.OnClickListener" />
 
 
+
+        <variable
+            name="onStepAgreeClickListener"
+            type="android.view.View.OnClickListener" />
+
         <variable
         <variable
             name="onStepOneDisagreeClickListener"
             name="onStepOneDisagreeClickListener"
             type="android.view.View.OnClickListener" />
             type="android.view.View.OnClickListener" />
@@ -236,7 +241,7 @@
                 android:layout_height="0dp"
                 android:layout_height="0dp"
                 android:background="@drawable/bg_common_btn"
                 android:background="@drawable/bg_common_btn"
                 android:gravity="center"
                 android:gravity="center"
-                android:onClick="@{onAgreeClickListener}"
+                android:onClick="@{onStepAgreeClickListener}"
                 android:text="@string/agreement_consider_it"
                 android:text="@string/agreement_consider_it"
                 android:textColor="@color/white"
                 android:textColor="@color/white"
                 android:textStyle="bold"
                 android:textStyle="bold"

+ 2 - 1
app/src/main/res/layout/item_order.xml

@@ -129,6 +129,7 @@
             tools:text="259647" />
             tools:text="259647" />
 
 
         <TextView
         <TextView
+            android:id="@+id/tv_auth_code_copy"
             isGone="@{!orderBean.isShowLink}"
             isGone="@{!orderBean.isShowLink}"
             android:background="@drawable/bg_order_auth_copy"
             android:background="@drawable/bg_order_auth_copy"
             android:layout_marginStart="6dp"
             android:layout_marginStart="6dp"
@@ -164,7 +165,7 @@
             android:layout_width="wrap_content"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginStart="16dp"
             android:layout_marginStart="16dp"
-            android:text="@{DateUtil.formatNormalDate(DateUtil.YYYY_MM_DD,orderBean.startTimestamp)}"
+            android:text="@{DateUtil.formatNormalDate(DateUtil.YYYY_MM_DD_HH_MM_SS,orderBean.startTimestamp)}"
             app:layout_constraintBaseline_toBaselineOf="@+id/tv_order_buy_time"
             app:layout_constraintBaseline_toBaselineOf="@+id/tv_order_buy_time"
             app:layout_constraintStart_toEndOf="@+id/tv_order_buy_time"
             app:layout_constraintStart_toEndOf="@+id/tv_order_buy_time"
             tools:text="2023-12-16" />
             tools:text="2023-12-16" />

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -181,4 +181,6 @@
     <string name="dialog_no_login">您需要先登录才能使用服务</string>
     <string name="dialog_no_login">您需要先登录才能使用服务</string>
     <string name="dialog_no_login_title">请登录</string>
     <string name="dialog_no_login_title">请登录</string>
     <string name="order_auth_code">授权编码</string>
     <string name="order_auth_code">授权编码</string>
+    <string name="net_error">网络异常</string>
+    <string name="account_logout_fail">登出失败</string>
 </resources>
 </resources>