Эх сурвалжийг харах

Merge branch 'feature/拦截非设备指定账户登录' into develop

Zhenghanjv 2 долоо хоног өмнө
parent
commit
1898cc96db

+ 2 - 2
app/build.gradle

@@ -21,8 +21,8 @@ android {
         applicationId "com.doverfuelingsolutions.issp"
         minSdkVersion 22
         targetSdkVersion 26
-        versionCode 24
-        versionName "1.2.11"
+        versionCode 25
+        versionName "1.2.12"
         archivesBaseName = versionName + "." + getTime()
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

+ 23 - 0
app/src/main/java/com/doverfuelingsolutions/issp/api/SystemApi.kt

@@ -39,6 +39,28 @@ object SystemApi {
     private var serviceAssets = makeAssetsService()
     private var serviceCheck = makeCheckService()
 
+    /**
+     * 获取账户对应设备
+     */
+    suspend fun getUserDevice(accountName: String,SN:String) = suspendCoroutine<DFSResult<Boolean>> {
+        DFSLog.i("开始获取账户对应设备:当前账户:${accountName},设备:${SN}")
+        serviceCheck.getUserDevice(accountName).enqueue(object :Callback<UserDevice>{
+            override fun onResponse(call: Call<UserDevice>, response: Response<UserDevice>) {
+                val code = response.code()
+                val body = response.body()
+                DFSLog.i("获取账户对应设备$body")
+
+                val find = body?.result?.find { it.Key.equals(accountName) && it.Value.equals(SN) }
+                it.resume(DFSResult.success(find != null))
+            }
+
+            override fun onFailure(call: Call<UserDevice>, t: Throwable) {
+                DFSLog.e("获取账户对应设备失败",t.message)
+                it.resume(DFSResult.fail("获取账户对应设备失败,${t.message}"))
+            }
+        })
+    }
+
     /**
      * 登录 + 获取油站信息
      */
@@ -527,6 +549,7 @@ object SystemApi {
         serviceTrx = makeTrxService()
         servicePay = makePayService()
         serviceConfig = makeConfigService()
+        serviceCheck = makeCheckService()
     }
 
     /**

+ 7 - 1
app/src/main/java/com/doverfuelingsolutions/issp/api/WayneApiConfig.kt

@@ -41,10 +41,12 @@ class WayneApiConfig {
         const val PORT_TRX_DEFAULT = "8699"
         const val PORT_CONFIG_DEFAULT = "8889"
         const val PORT_ASSETS_DEFAULT = "8080"
+        const val PORT_MIDDLE_TOOL_DEFAULT = "8721"
         private const val HOST_BASE_DEFAULT = "$DOMAIN_DEFAULT:$PORT_BASE_DEFAULT"
         private const val HOST_TRX_DEFAULT = "$DOMAIN_DEFAULT:$PORT_TRX_DEFAULT"
         private const val HOST_CONFIG_DEFAULT = "$DOMAIN_DEFAULT:$PORT_CONFIG_DEFAULT"
         private const val HOST_ASSETS_DEFAULT = "$DOMAIN_DEFAULT:$PORT_ASSETS_DEFAULT"
+        private const val HOST_MIDDLE_TOOL_DEFAULT = "$DOMAIN_DEFAULT_RELEASE:$PORT_MIDDLE_TOOL_DEFAULT"
         // 默认值 - 中控
         const val MIDDLE_IP_DEFAULT = "192.168.1.80"
         const val MIDDLE_PORT_DEFAULT = "4711"
@@ -82,7 +84,11 @@ class WayneApiConfig {
             return if (domain.isEmpty() || port.isEmpty()) HOST_ASSETS_DEFAULT else "$domain:$port"
         }
         val CHECK_ORDER_BASE:String get() {
-            return "http://tkhs.net.cn:8721"  //生产
+            val domain = SPUtil.getString(SPKeys.SERVER_DOMAIN)
+            val port = SPUtil.getString(SPKeys.SERVER_PORT_TOOL)
+            return if (domain.isEmpty() || port.isEmpty()) HOST_MIDDLE_TOOL_DEFAULT else "$domain:$port"
+
+//            return "http://tkhs.net.cn:8721"  //生产
 //            return "http://47.97.120.160:8721"//测试
 //            return "http://47.101.220.106:8721" //开发
         }

+ 25 - 0
app/src/main/java/com/doverfuelingsolutions/issp/api/dto/UserDevice.kt

@@ -0,0 +1,25 @@
+package com.doverfuelingsolutions.issp.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class UserDevice(
+    var result: List<UserDeviceValue>? = null,
+
+    var statusCode: String? = null,
+
+    var message: String? = null
+
+
+)
+
+data class UserDeviceValue(
+    /**
+     * 账户
+     */
+    var Key: String? = null,
+
+    /**
+     * 设备sn
+     */
+    var Value: String? = null
+)

+ 4 - 0
app/src/main/java/com/doverfuelingsolutions/issp/api/service/ServiceCheck.kt

@@ -4,6 +4,7 @@ import com.doverfuelingsolutions.issp.api.WayneApiConfig
 import com.doverfuelingsolutions.issp.api.dto.CheckRequest
 import com.doverfuelingsolutions.issp.api.dto.CheckResponse
 import com.doverfuelingsolutions.issp.api.dto.ResultPayment
+import com.doverfuelingsolutions.issp.api.dto.UserDevice
 import com.wayne.www.waynelib.webservice.entity.PosTrxMop
 import retrofit2.Call
 import retrofit2.http.*
@@ -19,4 +20,7 @@ interface ServiceCheck {
         @Query("NozzleId") nozzleId:String,
         @Query("sn") sn: String,
         @Query("token") token:String = "123456789"): Call<CheckResponse>
+
+    @GET("api/Account/GetUserDevice")
+    fun getUserDevice(@Query("UserID") userName:String):Call<UserDevice>
 }

+ 1 - 0
app/src/main/java/com/doverfuelingsolutions/issp/utils/sp/SPKeys.kt

@@ -28,6 +28,7 @@ class SPKeys {
         val SERVER_PORT_TRX: String = StringUtil.get(R.string.sp_server_port_trx)
         val SERVER_PORT_CONFIG: String = StringUtil.get(R.string.sp_server_port_config)
         val SERVER_PORT_ASSETS: String = StringUtil.get(R.string.sp_server_port_assets)
+        val SERVER_PORT_TOOL: String = StringUtil.get(R.string.sp_server_port_tool)
         val MIDDLE_IP: String = StringUtil.get(R.string.sp_middle_ip)
         val MIDDLE_PORT: String = StringUtil.get(R.string.sp_middle_port)
         val MIDDLE_WORKSTATION_ID: String = StringUtil.get(R.string.sp_middle_workstation_id)

+ 8 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/LoginActivity.kt

@@ -2,6 +2,7 @@ package com.doverfuelingsolutions.issp.view
 
 import android.content.Context
 import android.content.Intent
+import android.os.Build
 import android.os.Bundle
 import android.view.View
 import androidx.activity.viewModels
@@ -107,6 +108,7 @@ class LoginActivity : AppCompatActivity(),
             val password = loginViewModel.password.value
             when {
                 accountName.isNullOrBlank() || password.isNullOrBlank() -> snackbar.setText(R.string.input_not_right).show()
+                !isRightAccountAndDevice(accountName) -> snackbar.setText(R.string.error_account_device).show()
                 else -> {
                     val result = SystemApi.login(accountName, password)
                     if (!result.success) snackbar.setText(StringUtil.get(R.string.login_fail_reason, result.message)).show()
@@ -154,6 +156,12 @@ class LoginActivity : AppCompatActivity(),
         finish()
     }
 
+    private suspend fun isRightAccountAndDevice(accountName:String):Boolean{
+        val userDevice = SystemApi.getUserDevice(accountName, GlobalData.serialNumber.get())
+
+        return userDevice.success && userDevice.data == true
+    }
+
     class LoginViewModel : ViewModel() {
         val accountName = MutableLiveData(GlobalData.accountName.get())
         val password = MutableLiveData(GlobalData.password.get())

+ 13 - 12
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentOrderList.kt

@@ -238,18 +238,19 @@ class FragmentOrderList private constructor() : FragmentBasic(),RefreshOrder {
                         DFSLog.w("barcodeId:$barcodeId")
                     }
 
-                    // 获取云订单(本地需要缓存,避免重复生成订单)
-                    var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
-                    if (posTrx == null) {
-                        val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
-                        if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
-                            posTrx = resultReportPayment.data
-                            SPUtil.addWayneOrder(dc, posTrx)
-                        } else {
-                            dialog.dismiss()
-                            (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
-                            DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
-                        }
+                    // 获取云订单(本地需要缓存,避免重复生成订单),2025-07 ,从接口处理,不需要再缓存
+//                    var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
+//                    if (posTrx == null) {
+//
+//                    }
+                    var posTrx:PosTrx? = null
+                    val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
+                    if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
+                        posTrx = resultReportPayment.data
+                    } else {
+                        dialog.dismiss()
+                        (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
+                        DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
                     }
 
                     // 锁定订单

+ 13 - 12
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentPayType.kt

@@ -112,18 +112,19 @@ class FragmentPayType private constructor(): FragmentBasic(), View.OnClickListen
                 DFSLog.w("barcodeId:$barcodeId")
             }
 
-            // 获取云订单(本地需要缓存,避免重复生成订单)
-            var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
-            if (posTrx == null) {
-                val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
-                if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
-                    posTrx = resultReportPayment.data
-                    SPUtil.addWayneOrder(dc, posTrx)
-                } else {
-                    dialog.dismiss()
-                    (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
-                    DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
-                }
+            // 获取云订单(本地需要缓存,避免重复生成订单),2025-07 ,从接口处理,不需要再缓存
+//                    var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
+//                    if (posTrx == null) {
+//
+//                    }
+            var posTrx:PosTrx? = null
+            val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
+            if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
+                posTrx = resultReportPayment.data
+            } else {
+                dialog.dismiss()
+                (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
+                DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
             }
 
             // 锁定订单

+ 2 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentPreference.kt

@@ -24,6 +24,7 @@ class FragmentPreference : PreferenceFragmentCompat(), EditTextPreference.OnBind
         setNumberInput(SPKeys.SERVER_PORT_TRX)
         setNumberInput(SPKeys.SERVER_PORT_CONFIG)
         setNumberInput(SPKeys.SERVER_PORT_ASSETS)
+        setNumberInput(SPKeys.SERVER_PORT_TOOL)
         setNumberInput(SPKeys.MIDDLE_PORT)
         setNumberInput(SPKeys.MIDDLE_WORKSTATION_ID)
         setNumberInput(SPKeys.FUEL_PORT)
@@ -48,6 +49,7 @@ class FragmentPreference : PreferenceFragmentCompat(), EditTextPreference.OnBind
             SPKeys.SERVER_PORT_TRX,
             SPKeys.SERVER_PORT_CONFIG,
             SPKeys.SERVER_PORT_ASSETS,
+            SPKeys.SERVER_PORT_TOOL,
             SPKeys.MIDDLE_PORT,
             SPKeys.MIDDLE_WORKSTATION_ID,
             SPKeys.FUEL_PORT,

+ 25 - 11
app/src/main/java/com/doverfuelingsolutions/issp/view/util/LoginTokenRefresher.kt

@@ -1,6 +1,7 @@
 package com.doverfuelingsolutions.issp.view.util
 
 import android.app.Activity
+import android.os.Build
 import androidx.core.os.bundleOf
 import com.doverfuelingsolutions.issp.R
 import com.doverfuelingsolutions.issp.api.SystemApi
@@ -22,6 +23,15 @@ class LoginTokenRefresher {
             val expireMoment = GlobalData.accessTokenExpire.get()
             val delayTime = expireMoment - 480_000 - System.currentTimeMillis()
             if (delayTime > 0) delay(delayTime)
+
+            val userDevice = SystemApi.getUserDevice(GlobalData.accountName.get(), GlobalData.serialNumber.get())
+            if (!userDevice.success || userDevice.data != true) {
+                DFSLog.d("loginToken refresh 账户与设备不符合")
+                val msg = StringUtil.get(R.string.error_account_device)
+                toLogin(msg,activity)
+                return@launch
+            }
+
             val result = SystemApi.login(GlobalData.accountName.get(), GlobalData.password.get())
             if (result.success) {
                 DFSLog.d("loginToken refresh succeeded")
@@ -29,18 +39,8 @@ class LoginTokenRefresher {
                 start(activity)
             } else {
                 DFSLog.d("loginToken refresh failed: ${result.message}")
-                GlobalData.isLogin = false
                 val msg = StringUtil.get(R.string.fail_refresh_login)
-                DFSToastUtil.fail(msg)
-                // Back to login.
-                activity.finish()
-                LoginActivity.start(
-                    activity,
-                    bundleOf(
-                        Pair(LoginActivity.autoLogin, false),
-                        Pair(LoginActivity.loginMessage, msg),
-                    )
-                )
+                toLogin(msg,activity)
             }
         }
     }
@@ -50,4 +50,18 @@ class LoginTokenRefresher {
             if (it.isActive) it.cancel()
         }
     }
+
+    fun toLogin(msg:String,activity: Activity){
+        GlobalData.isLogin = false
+        DFSToastUtil.fail(msg)
+        // Back to login.
+        activity.finish()
+        LoginActivity.start(
+            activity,
+            bundleOf(
+                Pair(LoginActivity.autoLogin, false),
+                Pair(LoginActivity.loginMessage, msg),
+            )
+        )
+    }
 }

+ 1 - 0
app/src/main/res/values/keys.xml

@@ -18,6 +18,7 @@
     <string name="sp_server_port_trx">server_port_trx</string>
     <string name="sp_server_port_config">server_port_config</string>
     <string name="sp_server_port_assets">server_port_assets</string>
+    <string name="sp_server_port_tool">server_port_tool</string>
     <string name="sp_middle_ip">middle_ip</string>
     <string name="sp_middle_port">middle_port</string>
     <string name="sp_middle_workstation_id">middle_workstation_id</string>

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

@@ -48,6 +48,7 @@
     <string name="fail_operate">操作失败</string>
     <string name="in_loading">加载中&#8230;</string>
     <string name="input_not_right">填写数据不正确</string>
+    <string name="error_account_device">该账户不能在此设备登录</string>
     <string name="return_data_error">请求返回数据不正确</string>
     <string name="account_name_password_error">账号名或密码错误</string>
     <string name="bu_null">BU值为空</string>
@@ -71,6 +72,7 @@
     <string name="port_config">配置端口</string>
     <string name="port_assets">资源端口</string>
     <string name="port_update">升级端口</string>
+    <string name="port_tool">工具端口</string>
     <string name="middle_info">中控信息</string>
     <string name="workstation_id">workstationId</string>
     <string name="fuel_info">加油信息</string>

+ 7 - 0
app/src/main/res/xml/root_preferences.xml

@@ -47,6 +47,13 @@
             app:key="@string/sp_server_port_assets"
             app:title="@string/port_assets"
             app:useSimpleSummaryProvider="true" />
+
+        <EditTextPreference
+            app:dialogTitle="@string/hint_port_input"
+            android:defaultValue="8721"
+            app:key="@string/sp_server_port_tool"
+            app:title="@string/port_tool"
+            app:useSimpleSummaryProvider="true" />
     </PreferenceCategory>
 
     <PreferenceCategory app:title="@string/middle_info">