消费
diff --git a/app/build.gradle b/app/build.gradle
index 3881173..63e7988 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -67,6 +67,7 @@
compile 'com.android.support:multidex:1.0.3'
compile 'org.jetbrains.kotlin:kotlin-reflect:1.3.41'
compile 'org.springframework.android:spring-android-core:1.0.1.RELEASE'
- compile files('libs/apache-httpcomponents-httpcore.jar')
+ compile 'org.apache.httpcomponents:httpcore:4.4.10'
+// compile files('libs/apache-httpcomponents-httpcore.jar')
compile files('libs/zxinglibsl.jar')
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6830380..78ca339 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -71,10 +71,6 @@
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
</intent-filter>
-
- <meta-data
- android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
- android:resource="@xml/device_filter"/>
</activity>
<service android:name=".activities.ServiceDemo">
@@ -83,11 +79,30 @@
</intent-filter>
</service>
- <!--<activity-->
- <!--android:name=".activities.consume.WaitActivity"-->
- <!--android:label="@string/title_activity_consume"-->
- <!--android:launchMode="singleInstance"/>-->
-
+ <activity
+ android:name=".activities.consume.ConsumeActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleInstance"/>
+ <activity
+ android:name=".activities.init.InitActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.cardlib.CardlibActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.load.LoadActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.unregister.UnregisterActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.upgrade.UpgradeAcvitity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
</application>
</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/SPApplication.kt b/app/src/main/java/com/supwisdom/activities/SPApplication.kt
index 16adb48..61e704d 100644
--- a/app/src/main/java/com/supwisdom/activities/SPApplication.kt
+++ b/app/src/main/java/com/supwisdom/activities/SPApplication.kt
@@ -15,6 +15,8 @@
**/
class SPApplication : MultiDexApplication() {
private var mPos: Pos? = null
+ @Volatile
+ private var epayLinking: Boolean = false //链路状态 true 联机
companion object {
@Volatile
@@ -36,6 +38,14 @@
return mPos!!
}
+ fun setEpayLinking(isOnline: Boolean) {
+ epayLinking = isOnline
+ }
+
+ fun isOnline(): Boolean {
+ return epayLinking
+ }
+
override fun onCreate() {
super.onCreate()
mInstance = this
diff --git a/app/src/main/java/com/supwisdom/activities/cardlib/CardlibActivity.kt b/app/src/main/java/com/supwisdom/activities/cardlib/CardlibActivity.kt
new file mode 100644
index 0000000..a85fbc5
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/cardlib/CardlibActivity.kt
@@ -0,0 +1,11 @@
+package com.supwisdom.activities.cardlib
+
+import com.supwisdom.activities.BaseActivity
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardlibActivity : BaseActivity() {
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/ConsumePresenter.kt b/app/src/main/java/com/supwisdom/activities/consume/ConsumePresenter.kt
new file mode 100644
index 0000000..d42ccfc
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/ConsumePresenter.kt
@@ -0,0 +1,8 @@
+package com.supwisdom.activities.consume
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ConsumePresenter constructor(iConsumeView: IConsumeView){
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardBean.kt
new file mode 100644
index 0000000..162ff9b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.activities.consume.bean
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardBean {
+ var cardphyid: String? = null
+ var cardNo: String? = null
+ var idCard: String? = null
+ var expireDate: String? = null
+ var datetime: String? = null
+ var amount: Int = 0
+ var username: String? = null
+ var userid: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayConfirmRetBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayConfirmRetBean.kt
new file mode 100644
index 0000000..d469a56
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayConfirmRetBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayConfirmRetBean : BaseResp() {
+ var amount: Int = 0
+ var extraamt: Int = 0
+ var balance: Int = 0
+ var require_query: Boolean = false
+// var username: String? = null
+// var userid: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayInitRetBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayInitRetBean.kt
new file mode 100644
index 0000000..074e62c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayInitRetBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayInitRetBean : BaseResp() {
+ var billno: String? = null
+ var username: String? = null
+ var userid: Int = 0
+ var anonymous: Boolean = false
+ var sourcetype: String? = null
+ var needpwdconfirm: Boolean = false
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardUserInfoBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardUserInfoBean.kt
new file mode 100644
index 0000000..1fd28f2
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardUserInfoBean.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardUserInfoBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var username: String? = null
+ var showtime: Int = 3
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/mode/CardPayService.kt b/app/src/main/java/com/supwisdom/activities/consume/mode/CardPayService.kt
new file mode 100644
index 0000000..c11c4d8
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/mode/CardPayService.kt
@@ -0,0 +1,284 @@
+package com.supwisdom.activities.consume.mode
+
+import android.os.Handler
+import android.os.Message
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.IConsumeView
+import com.supwisdom.activities.consume.bean.CardBean
+import com.supwisdom.activities.consume.bean.CardPayConfirmRetBean
+import com.supwisdom.activities.consume.bean.CardPayInitRetBean
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.entity.TransdtlOfflineRecord
+import com.supwisdom.entity.TransdtlOnlineRecord
+import com.supwisdom.epaycard.Cardlib
+import com.supwisdom.exception.CardNotFoundError
+import com.supwisdom.exception.CardPayCancelFailError
+import com.supwisdom.exception.CardPayFailError
+import com.supwisdom.okhttp.TransResp
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.GsonUtil
+import com.supwisdom.utils.PublicDef
+import org.apache.http.HttpStatus
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayService constructor(iConsumeView: IConsumeView, handler: Handler) {
+ private val iConsumeView = iConsumeView
+ private val handler = handler
+ private val pos = SPApplication.getInstance().getPos()
+ private val runnable = CardPayRunnable()
+ private val consumeApi = ConsumeApi()
+ @Volatile
+ private var isExist = false
+ @Volatile
+ private var clickStat = ClickStat.INIT
+ @Volatile
+ private var amount: Int = 0
+ private var thread: Thread? = null
+ private lateinit var cardBean: CardBean
+
+ fun start() {
+ isExist = false
+ if (thread == null) {
+ thread = Thread(runnable)
+ thread!!.start()
+ }
+ }
+
+ fun stop() {
+ isExist = true
+ thread?.interrupt()
+ thread = null
+ }
+
+ private inner class CardPayRunnable : Runnable {
+ private lateinit var onlRecord: TransdtlOnlineRecord
+ private lateinit var offRecord: TransdtlOfflineRecord
+ override fun run() {
+ while (!isExist) {
+ CommonUtil.doSleep(100)
+ try {
+ readCard()
+ when (clickStat) {
+ ClickStat.PAY -> {
+ try {
+ doConsume()
+ } catch (ex: CardPayFailError) {
+ sendMsg(PublicDef.MSG_CARD_PAY_FAIL, getErrorInfo(ex.message))
+ clickStat = ClickStat.INIT
+ }
+ }
+ ClickStat.REVERSE -> {
+ try {
+ doReverse()
+ } catch (ex: CardPayCancelFailError) {
+ sendMsg(PublicDef.MSG_CARD_PAYCANCEL_FAIL, getErrorInfo(ex.message))
+ clickStat = ClickStat.INIT
+ }
+ }
+ ClickStat.INIT -> {
+
+ }
+ }
+ } catch (ex: CardNotFoundError) {
+ ex.printStackTrace()
+ continue
+ }
+
+ }
+ }
+
+ private fun readCard() {
+ val cardphyid = Cardlib.instance.requestCard()
+ val cardinfo = Cardlib.instance.readCard()
+ cardBean = CardBean()
+ cardBean.cardphyid = cardphyid
+ cardBean.cardNo = cardinfo.cardNo
+ cardBean.idCard = cardinfo.idCard
+ cardBean.expireDate = cardinfo.expireDate
+ cardBean.amount = amount
+ cardBean.datetime = DateUtil.getNowDateTimeFormat()
+ }
+
+ private fun doConsume() {
+ sendMsg(PublicDef.MSG_CARD_PAYING, "正在扣款...")
+ if (SPApplication.getInstance().isOnline()) {
+ if (!doOnlineConsume()) {
+ /**
+ * 由于不写卡,联机消费失败直接转离线
+ */
+ doOfflineConsume()
+ }
+ } else {
+ doOfflineConsume()
+ }
+ }
+
+ private fun doReverse() {
+ throw CardPayCancelFailError("暂不支持")
+ }
+
+ private fun doOnlineConsume(): Boolean {
+ initTransdtlOnline()
+ var resp = consumeApi.payInit(onlRecord)
+ var result = parseInitResult(resp)
+ if (!result) {
+ return result
+ }
+ resp = consumeApi.payConfirm(onlRecord)
+ result = parseConfirmResult(resp)
+ updateTransdtlOnline(result)
+ return result
+ }
+
+ private fun parseInitResult(resp: TransResp?): Boolean {
+ if (resp == null || resp.retcode != HttpStatus.SC_OK) {
+ SPApplication.getInstance().setEpayLinking(false)
+ return false
+ }
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardPayInitRetBean::class.java)
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw CardPayFailError(retBean.retmsg!!)
+ }
+ onlRecord.billno = retBean.billno
+ onlRecord.username = retBean.username
+ onlRecord.userid = retBean.userid
+ return true
+ }
+
+ private fun parseConfirmResult(resp: TransResp?): Boolean {
+ if (resp == null || resp.retcode != HttpStatus.SC_OK) {
+ SPApplication.getInstance().setEpayLinking(false)
+ return false
+ }
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardPayConfirmRetBean::class.java)
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw CardPayFailError(retBean.retmsg!!)
+ }
+ if (retBean.require_query) {
+ //TODO
+ throw CardPayFailError("查询未实现")
+ }
+ onlRecord.payamt = retBean.amount
+ onlRecord.extraamt = retBean.extraamt
+ return true
+ }
+
+ private fun initTransdtlOnline() {
+ onlRecord = TransdtlOnlineRecord()
+ var seqno = pos.getTransdtlOnlineMaxSeqno()
+ if (seqno == 0) {
+ seqno = pos.getControlPara(PublicDef.CONTROL_TRANSDTLONL_SEQNO)?.paraval?.toInt() ?: 0
+ }
+ onlRecord.devphyid = pos.getConfigPara()!!.devphyid
+ onlRecord.transdate = cardBean.datetime!!.substring(0, 8)
+ onlRecord.transtime = cardBean.datetime!!.substring(8)
+ onlRecord.devseqno = seqno
+ onlRecord.cardno = cardBean.cardNo
+ onlRecord.cardphyid = cardBean.cardphyid
+ onlRecord.payamt = cardBean.amount
+ onlRecord.extraamt = 0
+ onlRecord.transtype = "card"
+ onlRecord.status = "init"
+ onlRecord.upflag = 1
+ if (!pos.saveTransdtlOnline(onlRecord)) {
+ throw CardPayFailError("保存流水失败")
+ }
+ }
+
+ private fun updateTransdtlOnline(issuccess: Boolean) {
+ if (issuccess) {
+ onlRecord.status = "suc"
+ } else {
+ onlRecord.status = "fail"
+ }
+ onlRecord.upflag = 0
+ if (!pos.updateTransdtlOnline(onlRecord)) {
+ throw CardPayFailError("更新流水失败")
+ }
+ }
+
+ private fun doOfflineConsume() {
+ initTransdtlOffline()
+ checkCardValid()
+ updateTransdtlOffline(true)
+ }
+
+ private fun checkCardValid() {
+ val sysRecord = pos.getSysPara()
+ if (!sysRecord!!.offlineEnable) {
+ throw CardPayFailError("禁止离线交易")
+ }
+ val offdate = DateUtil.getDayDateNoFormatBefore(sysRecord.maxOfflineDays)
+ val validdate = pos.getDynamicPara()!!.lastauthtime?.substring(0, 8) ?: "00000000"
+ if (offdate > validdate) {
+ throw CardPayFailError("设备已脱机${sysRecord.maxOfflineDays}天")
+ }
+
+ val whiteRecord =
+ pos.getWhiteList(offRecord.cardphyid!!, offRecord.cardno!!) ?: throw CardPayFailError("卡无权限")
+ if (whiteRecord.flag == 1) {
+ throw CardPayFailError("卡已锁定")
+ }
+ if (whiteRecord.balance < offRecord.payamt) {
+ throw CardPayFailError("请到联机设备使用")
+ }
+ }
+
+ private fun initTransdtlOffline() {
+ offRecord = TransdtlOfflineRecord()
+ var seqno = pos.getTransdtlOfflineMaxSeqno()
+ if (seqno == 0) {
+ seqno = pos.getControlPara(PublicDef.CONTROL_TRANSDTLOFF_SEQNO)?.paraval?.toInt() ?: 0
+ }
+ offRecord.devphyid = pos.getConfigPara()!!.devphyid
+ offRecord.transdate = cardBean.datetime!!.substring(0, 8)
+ offRecord.transtime = cardBean.datetime!!.substring(8)
+ offRecord.devseqno = seqno
+ offRecord.cardno = cardBean.cardNo
+ offRecord.cardphyid = cardBean.cardphyid
+ offRecord.payamt = cardBean.amount
+ offRecord.extraamt = 0
+ offRecord.managefeetype = "none"
+ offRecord.status = "init"
+ offRecord.upflag = 1
+ if (!pos.saveTransdtlOffline(offRecord)) {
+ throw CardPayFailError("保存流水失败")
+ }
+ }
+
+ private fun updateTransdtlOffline(issuccess: Boolean) {
+ if (issuccess) {
+ offRecord.status = "suc"
+ } else {
+ offRecord.status = "fail"
+ }
+ offRecord.upflag = 0
+ if (!pos.updateTransdtlOffline(offRecord)) {
+ throw CardPayFailError("更新流水失败")
+ }
+ }
+
+ private fun getErrorInfo(errmsg: String?): CardUserInfoBean {
+ val info = CardUserInfoBean(PublicDef.ERROR, errmsg ?: "null")
+ info.showtime = pos.getSysPara()!!.consumeFailShowtime
+ return info
+ }
+
+ private fun sendMsg(code: Int, obj: Any) {
+ val msg = Message()
+ msg.what = code
+ msg.obj = obj
+ handler.sendMessage(msg)
+ }
+ }
+}
+
+enum class ClickStat {
+ INIT,
+ PAY,
+ REVERSE
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/ConsumeApi.kt b/app/src/main/java/com/supwisdom/activities/consume/mode/ConsumeApi.kt
similarity index 97%
rename from app/src/main/java/com/supwisdom/service/ConsumeApi.kt
rename to app/src/main/java/com/supwisdom/activities/consume/mode/ConsumeApi.kt
index 5b460fa..54627af 100644
--- a/app/src/main/java/com/supwisdom/service/ConsumeApi.kt
+++ b/app/src/main/java/com/supwisdom/activities/consume/mode/ConsumeApi.kt
@@ -1,4 +1,4 @@
-package com.supwisdom.service
+package com.supwisdom.activities.consume.mode
import com.supwisdom.activities.YktSession
import com.supwisdom.entity.TransdtlOnlineRecord
diff --git a/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt b/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt
index 701e029..d72769f 100644
--- a/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt
+++ b/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt
@@ -4,7 +4,14 @@
import android.os.Looper
import android.os.Message
import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.YktSession
+import com.supwisdom.entity.ControlParaRecord
+import com.supwisdom.service.AuthEpay
+import com.supwisdom.service.EpayApiImpl
import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.utils.ThreadPool
+import java.lang.Exception
/**
** create by zzq on 2019/7/24
@@ -25,6 +32,7 @@
private val LOAD_DONE = 3
private var hasInit: Boolean = false
+ @Volatile
private var loading: Boolean = false
fun isLoading(): Boolean {
@@ -32,7 +40,90 @@
}
fun start() {
+ loading = true
+ var cfgRecord = pos.getConfigPara()
+ hasInit = cfgRecord?.initOK ?: false
+ YktSession.getInstance().setWebAPISession(
+ cfgRecord!!.epayIP!!,
+ cfgRecord.epayPort,
+ cfgRecord.epayUri!!,
+ cfgRecord.devphyid!!,
+ CommonUtil.getCommunicateTime()
+ )
+
+ ThreadPool.getShortPool().execute(Runnable {
+ sendMessage(LOAD_PROGRESS, "正在系统签到...")
+ val apiInterface = EpayApiImpl()
+ val bean = AuthEpay().login()
+ if (bean.retcode != PublicDef.SUCCESS) {
+ sendMessage(LOAD_DONE, bean.retmsg!!)
+ loading = false
+ if (!hasInit) {
+ sendMessage(JUMP_TO_UNREGISTER, "签到错误:${bean.retcode},${bean.retmsg}")
+ return@Runnable
+ }
+ } else {
+ cfgRecord = pos.getConfigPara()
+ cfgRecord!!.deviceid = bean.deviceid
+ cfgRecord!!.merchaccno = bean.merchaccno
+ cfgRecord!!.shopname = bean.shopname
+ pos.replaceConfigPara(cfgRecord!!)
+
+ // 保存流水号
+ if (!hasInit) {
+ saveControlPara(PublicDef.CONTROL_TRANSDTLONL_SEQNO, bean.onlineseqno.toString())
+ saveControlPara(PublicDef.CONTROL_TRANSDTLOFF_SEQNO, bean.offlineseqno.toString())
+ }
+
+ SPApplication.getInstance().setEpayLinking(true)
+ sendMessage(LOAD_DONE, "系统签到成功")
+ }
+
+ // 设置通讯参数
+// YktSession.getInstance().setSessionKey(pos.getDynamicPara().getSessionKey())
+ try {
+ sendMessage(LOAD_PROGRESS, "加载系统参数...")
+ apiInterface.downloadSyspara(bean.paraverno, bean.paragroupid)
+ sendMessage(LOAD_DONE, "加载系统参数成功")
+ } catch (ex: Exception) {
+ sendMessage(LOAD_DONE, "加载系统参数失败:${ex.message}")
+ if (!hasInit) {
+ loading = false
+ return@Runnable
+ }
+ }
+
+ try {
+ sendMessage(LOAD_PROGRESS, "加载白名单...")
+ apiInterface.downloadWhitelist(bean.cardverno!!)
+ sendMessage(LOAD_DONE, "加载白名单成功")
+ } catch (ex: Exception) {
+ sendMessage(LOAD_DONE, "加载白名单失败:${ex.message}")
+ if (!hasInit) {
+ loading = false
+ return@Runnable
+ }
+ }
+
+ cfgRecord = pos.getConfigPara()
+ cfgRecord!!.initOK = true
+ pos.replaceConfigPara(cfgRecord!!)
+
+ val ctlRecord = pos.getControlPara(PublicDef.CONTROL_HAS_REGISTER) ?: ControlParaRecord()
+ ctlRecord.paraname = PublicDef.CONTROL_HAS_REGISTER
+ ctlRecord.paraval = "1"
+ pos.replaceControlPara(ctlRecord)
+
+ sendMessage(LOAD_SUCCESS, "加载成功")
+ })
+ }
+
+ private fun saveControlPara(paraname: String, paraval: String): Boolean {
+ val para = ControlParaRecord()
+ para.paraname = paraname
+ para.paraval = paraval
+ return pos.replaceControlPara(para)
}
private fun createHandler() {
diff --git a/app/src/main/java/com/supwisdom/activities/splash/SplashActivity.kt b/app/src/main/java/com/supwisdom/activities/splash/SplashActivity.kt
new file mode 100644
index 0000000..6e53f15
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/splash/SplashActivity.kt
@@ -0,0 +1,84 @@
+package com.supwisdom.activities.splash
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.cardlib.CardlibActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class SplashActivity : BaseActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_splash)
+ initView()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ refresh()
+ if (hasSdcardPermession()) {
+ processStart()
+ }
+ }
+
+ private fun processStart() {
+ CommonUtil.writeLinnuuxParams()
+ jumpActivity(CardlibActivity::class.java)
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("新开普智能设备")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDate())
+ AuxScreenController.getInstance().refreshContent(listOf<String>("欢迎使用智能设备"))
+ }
+
+ private fun initView() {
+ val tv = findViewById<View>(R.id.versionNumber) as TextView
+ tv.text = CommonUtil.getVersionName(applicationContext)
+ AuxScreenController.getInstance().open()
+ }
+
+ private val REQUEST_RETCODE = 99
+
+ private fun hasSdcardPermession(): Boolean {
+ /**
+ * 动态获取权限,Android 6.0 新特性,一些保护权限,除了要在AndroidManifest中声明权限,还要使用如下代码动态获取
+ */
+ if (Build.VERSION.SDK_INT >= 23) {
+ val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
+ //验证是否许可权限
+ for (str in permissions) {
+ if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
+ //申请权限
+ this.requestPermissions(permissions, REQUEST_RETCODE)
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_RETCODE) {
+ for (i in grantResults.indices) {
+ if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
+ return
+ }
+ }
+ // 请求权限的结果 true代表用户同意了
+ processStart()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/AuthRetBean.kt b/app/src/main/java/com/supwisdom/bean/AuthRetBean.kt
new file mode 100644
index 0000000..b488ac6
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/AuthRetBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class AuthRetBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var deviceid: Int = 0
+ var merchaccno: Int = 0
+ var shopname: String? = null
+ var onlineseqno: Int = 0
+ var offlineseqno: Int = 0
+ var paraverno: Int = 0
+ var paragroupid: Int = 0
+ var cardverno: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt b/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt
index d4c1de4..fe6dfc9 100644
--- a/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt
+++ b/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt
@@ -9,7 +9,7 @@
id,
returnFlag,
heatBeat,
- offlineFlag,
+ offlineEnable,
maxOfflineDays,
mngpasswd,
fixpayGap,
@@ -81,4 +81,11 @@
status,
upflag
}
+
+ enum class WhiteList {
+ cardphyid,
+ cardno,
+ flag,
+ balance
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/DBParaHelper.kt b/app/src/main/java/com/supwisdom/db/DBParaHelper.kt
index ff24314..ebcb7d8 100644
--- a/app/src/main/java/com/supwisdom/db/DBParaHelper.kt
+++ b/app/src/main/java/com/supwisdom/db/DBParaHelper.kt
@@ -18,6 +18,7 @@
val TABLE_NAME_SYSPARA = "tb_syspara"
val TABLE_NAME_DYNAMICPARA = "tb_dynamicpara"
val TABLE_NAME_CONTROLPARA = "tb_controlpara"
+ val TABLE_NAME_WHITELIST = "tb_whitelist"
private var instance: DBParaHelper? = null
fun getInstance(context: Context): DBParaHelper {
@@ -36,6 +37,15 @@
/**
* SQL for create table
*/
+ private val CREATE_TABLE_NAME_WHITELIST = ("create table IF NOT EXISTS "
+ + TABLE_NAME_WHITELIST + " ( "
+ + BeanPropEnum.WhiteList.cardphyid + " varchar(32),"
+ + BeanPropEnum.WhiteList.cardno + " varchar(32),"
+ + BeanPropEnum.WhiteList.flag + " integer,"
+ + BeanPropEnum.WhiteList.balance + " integer,"
+ + "primary key ("
+ + BeanPropEnum.WhiteList.cardphyid + ","
+ + BeanPropEnum.WhiteList.cardno + ") )")
private val CREATE_TABLE_NAME_CONTROLPARA = ("create table IF NOT EXISTS "
+ TABLE_NAME_CONTROLPARA + " ( "
@@ -55,7 +65,7 @@
+ BeanPropEnum.Syspara.id + " long primary key, "
+ BeanPropEnum.Syspara.returnFlag + " integer, "
+ BeanPropEnum.Syspara.heatBeat + " integer, "
- + BeanPropEnum.Syspara.offlineFlag + " integer, "
+ + BeanPropEnum.Syspara.offlineEnable + " integer, "
+ BeanPropEnum.Syspara.maxOfflineDays + " integer, "
+ BeanPropEnum.Syspara.mngpasswd + " char(6), "
+ BeanPropEnum.Syspara.fixpayGap + " integer, "
@@ -73,6 +83,7 @@
db.execSQL(CREATE_TABLE_NAME_SYSPARA)
db.execSQL(CREATE_TABLE_NAME_DYNAMICPARA)
db.execSQL(CREATE_TABLE_NAME_CONTROLPARA)
+ db.execSQL(CREATE_TABLE_NAME_WHITELIST)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
diff --git a/app/src/main/java/com/supwisdom/db/Pos.kt b/app/src/main/java/com/supwisdom/db/Pos.kt
index 79caa4b..205e656 100644
--- a/app/src/main/java/com/supwisdom/db/Pos.kt
+++ b/app/src/main/java/com/supwisdom/db/Pos.kt
@@ -17,8 +17,11 @@
private val sysParaDao = SysParaDao(context)
private var sysRecord: SysParaRecord? = null
private val controlParaDao = ControlParaDao(context)
+ private val whiteListDao = WhiteListDao(context)
private val transdtlOnlineDao = TransdtlOnlineDao(sdContext)
private val transdtlOfflineDao = TransdtlOfflineDao(sdContext)
+ private var onlMaxSeqno = 0
+ private var offMaxSeqno = 0
init {
}
@@ -119,6 +122,36 @@
return sysRecord
}
+ fun saveWhiteList(list: List<WhiteListRecord>): Boolean {
+ try {
+ whiteListDao.getLock().lock()
+ return whiteListDao.replace(list)
+ } finally {
+ whiteListDao.getLock().unlock()
+ }
+ }
+
+ fun getWhiteList(cardphyid: String, cardno: String): WhiteListRecord? {
+ try {
+ whiteListDao.getLock().lock()
+ return whiteListDao.get(cardphyid, cardno)
+ } finally {
+ whiteListDao.getLock().unlock()
+ }
+ }
+
+ fun getTransdtlOnlineMaxSeqno(): Int {
+ if (onlMaxSeqno == 0) {
+ try {
+ transdtlOnlineDao.getLock().lock()
+ onlMaxSeqno = transdtlOnlineDao.getMaxSeqno()
+ } finally {
+ transdtlOnlineDao.getLock().unlock()
+ }
+ }
+ return onlMaxSeqno
+ }
+
fun getTransdtlOnlineUnconfirm(): List<TransdtlOnlineRecord> {
try {
transdtlOnlineDao.getLock().lock()
@@ -155,6 +188,18 @@
}
}
+ fun getTransdtlOfflineMaxSeqno(): Int {
+ if (offMaxSeqno == 0) {
+ try {
+ transdtlOfflineDao.getLock().lock()
+ offMaxSeqno = transdtlOfflineDao.getMaxSeqno()
+ } finally {
+ transdtlOfflineDao.getLock().unlock()
+ }
+ }
+ return offMaxSeqno
+ }
+
fun getTransdtlOfflineUnconfirm(): List<TransdtlOfflineRecord> {
try {
transdtlOfflineDao.getLock().lock()
diff --git a/app/src/main/java/com/supwisdom/db/SysParaDao.kt b/app/src/main/java/com/supwisdom/db/SysParaDao.kt
index 8d3b045..e6676df 100644
--- a/app/src/main/java/com/supwisdom/db/SysParaDao.kt
+++ b/app/src/main/java/com/supwisdom/db/SysParaDao.kt
@@ -39,10 +39,11 @@
val values = getContentValues(record)
try {
db.beginTransaction()
- if (db.update(TABLE, values, BeanPropEnum.Syspara.id.toString() + "=?", arrayOf(INDEX)) > 0) {
- db.setTransactionSuccessful()
- return true
+ if (db.update(TABLE, values, BeanPropEnum.Syspara.id.toString() + "=?", arrayOf(INDEX)) < 0) {
+ return false
}
+ db.setTransactionSuccessful()
+ return true
} finally {
db.endTransaction()
}
@@ -84,7 +85,8 @@
val record = SysParaRecord()
record.returnFlag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.returnFlag.toString()))
record.heatBeat = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.heatBeat.toString()))
- record.offlineFlag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.offlineFlag.toString()))
+ val enable = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.offlineEnable.toString()))
+ record.offlineEnable = enable == 1
record.maxOfflineDays = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.maxOfflineDays.toString()))
record.mngPasswd = cursor.getString(cursor.getColumnIndex(BeanPropEnum.Syspara.mngpasswd.toString()))
record.fixpayGap = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.fixpayGap.toString()))
@@ -100,7 +102,11 @@
values.put(BeanPropEnum.Syspara.id.toString(), INDEX)
values.put(BeanPropEnum.Syspara.returnFlag.toString(), record.returnFlag)
values.put(BeanPropEnum.Syspara.heatBeat.toString(), record.heatBeat)
- values.put(BeanPropEnum.Syspara.offlineFlag.toString(), record.offlineFlag)
+ if (record.offlineEnable) {
+ values.put(BeanPropEnum.Syspara.offlineEnable.toString(), 1)
+ } else {
+ values.put(BeanPropEnum.Syspara.offlineEnable.toString(), 0)
+ }
values.put(BeanPropEnum.Syspara.maxOfflineDays.toString(), record.maxOfflineDays)
values.put(BeanPropEnum.Syspara.mngpasswd.toString(), record.mngPasswd)
values.put(BeanPropEnum.Syspara.fixpayGap.toString(), record.fixpayGap)
diff --git a/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt b/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt
index f3b3f6c..c2f158b 100644
--- a/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt
+++ b/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt
@@ -70,6 +70,21 @@
}
}
+ fun getMaxSeqno(): Int {
+ val db = dbHelper.readableDatabase
+ val sql = ("select max(${BeanPropEnum.TransdtlOffline.devseqno}) as seqno from $TABLE")
+ var cursor: Cursor? = null
+ try {
+ cursor = db.rawQuery(sql, null, null)
+ if (cursor != null && cursor.moveToNext()) {
+ return cursor.getInt(cursor.getColumnIndex("seqno"))
+ }
+ } finally {
+ cursor?.close()
+ }
+ return 0
+ }
+
fun clear(): Boolean {
val db = dbHelper.writableDatabase
try {
diff --git a/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt b/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt
index e4e7b55..c6a4f6d 100644
--- a/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt
+++ b/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt
@@ -70,6 +70,21 @@
}
}
+ fun getMaxSeqno(): Int {
+ val db = dbHelper.readableDatabase
+ val sql = ("select max(${BeanPropEnum.TransdtlOnline.devseqno}) as seqno from $TABLE")
+ var cursor: Cursor? = null
+ try {
+ cursor = db.rawQuery(sql, null, null)
+ if (cursor != null && cursor.moveToNext()) {
+ return cursor.getInt(cursor.getColumnIndex("seqno"))
+ }
+ } finally {
+ cursor?.close()
+ }
+ return 0
+ }
+
fun clear(): Boolean {
val db = dbHelper.writableDatabase
try {
diff --git a/app/src/main/java/com/supwisdom/db/WhiteListDao.kt b/app/src/main/java/com/supwisdom/db/WhiteListDao.kt
new file mode 100644
index 0000000..a5dfcdd
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/WhiteListDao.kt
@@ -0,0 +1,84 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.WhiteListRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class WhiteListDao constructor(context: Context) {
+ private val dbHelper = DBParaHelper.getInstance(context)
+ private val TABLE = DBParaHelper.TABLE_NAME_WHITELIST
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun replace(list: List<WhiteListRecord>): Boolean {
+ val db = dbHelper.readableDatabase
+ try {
+ db.beginTransaction()
+ list.forEach {
+ val values = getContentValues(it)
+ if (db.replace(TABLE, null, values) < 0) {
+ return false
+ }
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ fun get(cardphyid: String, cardno: String): WhiteListRecord? {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ val selection = BeanPropEnum.WhiteList.cardphyid.toString() + "=? and " + BeanPropEnum.WhiteList.cardno + "=?"
+ try {
+ cursor = db.query(TABLE, null, selection, arrayOf(cardphyid, cardno), null, null, null)
+ if (cursor != null && cursor.moveToNext()) {
+ return getRecord(cursor)
+ }
+ } finally {
+ cursor?.close()
+ }
+ return null
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): WhiteListRecord {
+ val record = WhiteListRecord()
+ record.cardphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.WhiteList.cardphyid.toString()))
+ record.cardno = cursor.getString(cursor.getColumnIndex(BeanPropEnum.WhiteList.cardno.toString()))
+ record.flag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.WhiteList.flag.toString()))
+ record.balance = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.WhiteList.balance.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: WhiteListRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.WhiteList.cardphyid.toString(), record.cardphyid)
+ values.put(BeanPropEnum.WhiteList.cardno.toString(), record.cardno)
+ values.put(BeanPropEnum.WhiteList.flag.toString(), record.flag)
+ values.put(BeanPropEnum.WhiteList.balance.toString(), record.balance)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt b/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt
index 2a7c948..3c344a7 100644
--- a/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt
+++ b/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt
@@ -2,7 +2,7 @@
/**
** create by zzq on 2019/7/24
- ** @desc
+ ** @desc 本地配置参数
**/
class ConfigParaRecord {
var mode: Int = 0//
diff --git a/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt b/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt
index 9028aa7..441d056 100644
--- a/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt
+++ b/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt
@@ -2,7 +2,7 @@
/**
** create by zzq on 2019/7/24
- ** @desc
+ ** @desc 本地控制参数
**/
class ControlParaRecord {
var paraname: String? = null
diff --git a/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt b/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt
index bb2a939..d396060 100644
--- a/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt
+++ b/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt
@@ -2,7 +2,7 @@
/**
** create by zzq on 2019/7/24
- ** @desc
+ ** @desc 后台动态参数
**/
class DynamicParaRecord {
var paraverno: Int = 0//参数版本
@@ -10,4 +10,5 @@
var cardverno: String? = null // 黑名单版本号 12byte
var jwt: String? = null
var token: String? = null
+ var lastauthtime: String? = null //最后一次认证时间 yyyyMMddhhmmss
}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt b/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt
index 288567e..adb38d9 100644
--- a/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt
+++ b/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt
@@ -2,12 +2,12 @@
/**
** create by zzq on 2019/7/24
- ** @desc
+ ** @desc 后台系统参数
**/
class SysParaRecord {
var returnFlag: Int = 0// 消费撤销开关 0bit -0x1表示冲正使能
var heatBeat: Int = 0// 心跳间隔
- var offlineFlag: Int = 0 // 脱机消费时限开关 0-关闭, 1-开启
+ var offlineEnable: Boolean = false // 脱机消费时限开关 false-关闭, true-开启
var maxOfflineDays: Int = 0// 最大脱机天数
var mngPasswd: String? = null// 维护密码
var consumeShowtime: Int = 0// 消费成功显示时间
diff --git a/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt b/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt
index ba06561..1037fb9 100644
--- a/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt
+++ b/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt
@@ -16,6 +16,8 @@
var payamt: Int = 0
var extraamt: Int = 0
var managefeetype: String? = null // none,discount,mealer
+ var username: String? = null
+ var userid: Int = 0
var billno: String? = null
var reversalflag: String? = null //消费null 自动冲正auto 手动撤销 manual
var reversalbillno: String? = null //被冲正交易参考号
diff --git a/app/src/main/java/com/supwisdom/entity/WhiteListRecord.kt b/app/src/main/java/com/supwisdom/entity/WhiteListRecord.kt
new file mode 100644
index 0000000..bbda15c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/WhiteListRecord.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc 白名单
+ **/
+class WhiteListRecord {
+ var cardphyid: String? = null
+ var cardno: String? = null
+ var flag: Int = 0 // 0--白卡 1--黑卡
+ var balance: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/ApduResponse.kt b/app/src/main/java/com/supwisdom/epaycard/ApduResponse.kt
new file mode 100644
index 0000000..ec0b7c7
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/ApduResponse.kt
@@ -0,0 +1,40 @@
+package com.supwisdom.epaycard
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ApduResponse constructor(val buffer: ByteArray) {
+ val sW1: Int
+ get() {
+ return buffer[buffer.size - 2].toInt() and 0xFF
+ }
+
+ val sW2: Int
+ get() {
+ return buffer[buffer.size - 1].toInt() and 0xFF
+ }
+
+ val sw: Int
+ get() {
+ return (sW1 shl 8) or sW2
+ }
+
+ val data: ByteArray
+ get() {
+ return buffer.copyOfRange(0, buffer.size - 2)
+ }
+
+ val bytes: ByteArray
+ get() {
+ return buffer
+ }
+
+ fun isOK(): Boolean {
+ return sW1 == 0x90 && sW2 == 0x00
+ }
+
+ fun swToString(): String {
+ return "%02X%02X".format(sW1, sW2)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/CardBaseInfoBean.kt b/app/src/main/java/com/supwisdom/epaycard/CardBaseInfoBean.kt
new file mode 100644
index 0000000..855b57c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/CardBaseInfoBean.kt
@@ -0,0 +1,22 @@
+package com.supwisdom.epaycard
+
+import com.supwisdom.utils.decodeBCD
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardBaseInfoBean constructor(val data: ByteArray) {
+ val cardNo: String
+ get() {
+ return data.copyOfRange(31, 42).decodeBCD()
+ }
+ val idCard: String
+ get() {
+ return data.copyOfRange(43, 60).decodeBCD()
+ }
+ val expireDate: String
+ get() {
+ return data.copyOfRange(61, 64).decodeBCD()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/Cardlib.kt b/app/src/main/java/com/supwisdom/epaycard/Cardlib.kt
new file mode 100644
index 0000000..4ee2bc0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/Cardlib.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.epaycard
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class Cardlib {
+ companion object {
+ @JvmStatic
+ val instance: EpayCardlib = EpayCardlib()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/DaliReader.kt b/app/src/main/java/com/supwisdom/epaycard/DaliReader.kt
new file mode 100644
index 0000000..4992921
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/DaliReader.kt
@@ -0,0 +1,154 @@
+package com.supwisdom.epaycard
+
+import android.os.Build
+import com.newcapec.jni.ApduResp
+import com.newcapec.jni.ApduSend
+import com.newcapec.jni.Picc
+import com.supwisdom.exception.CardNotFoundError
+import com.supwisdom.exception.CardlibInitError
+import com.supwisdom.exception.CardlibValueError
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.LogUtil
+import com.supwisdom.utils.encodeHex
+import com.supwisdom.utils.unsignedToInt
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class DaliReader {
+ private val TAG = "DaliReader"
+ private var cardTag = Picc.DetectInfo()
+ private var picc: Picc? = null
+
+ fun close() {
+ picc?.close()
+ picc = null
+ }
+
+ @Throws(CardlibInitError::class)
+ fun init() {
+ // CAP08S-V1.1.0.20181107 test-keys
+ //****设备固件版本>1.0.8c 使用新读卡驱动
+ /** 固件版本<=1.08 使用v108so ***/
+ /** 固件版本<=1.10 使用v110so ***/
+ /** 固件版本>=1.15 使用v115so ***/
+ /** 固件版本>=1.16 使用v116so ***/
+ val temp = Build.DISPLAY
+ val version = if (temp.contains("CAP08S-V1")) {
+ when {
+ temp < "CAP08S-V1.0.9" -> 108
+ temp < "CAP08S-V1.1.1" -> 110
+ else -> 115
+ }
+ } else {
+ /**
+ * v1.1.6
+ */
+ CommonUtil.getSerialNumber()?.replace("v", "")
+ ?.replace("V", "")
+ ?.replace(".", "")
+ ?.toInt() ?: 116
+ }
+ picc = Picc(version)
+ val ret = picc!!.open()
+ if (ret != 0) {
+ LogUtil.d(TAG, "A711Reader init error,ret=$ret")
+ throw CardlibInitError("加载卡库错误=$ret")
+ }
+ }
+
+ @Throws(CardNotFoundError::class)
+ fun requestCard(): String {
+ picc!!.remove('R'.toByte(), 0)
+ val ret = picc!!.detect('X'.toByte(), cardTag)
+ if (ret != 0) {
+ throw CardNotFoundError("寻卡错误=$ret")
+ }
+ val uidLen = cardTag.SerialInfo_Array[0].unsignedToInt()
+ val cardSN = cardTag.SerialInfo_Array.copyOfRange(1, 1 + uidLen)
+ return cardSN.encodeHex()
+ }
+
+ @Throws(CardlibValueError::class)
+ fun cpuApdu(cmd: ByteArray): ApduResponse {
+ val send = ApduSend()
+ val resp = ApduResp()
+ when {
+ cmd.size == 4 -> System.arraycopy(cmd, 0, send.Command, 0, 4)
+ cmd.size == 5 -> {
+ System.arraycopy(cmd, 0, send.Command, 0, 4)
+ send.Le = cmd[4].unsignedToInt().toShort()
+ if (0xB2 == cmd[1].unsignedToInt() &&
+ 0x84 == cmd[3].unsignedToInt()
+ ) {
+ //file 0x10
+ send.Le = 24
+ } else if (0xB2 == cmd[1].unsignedToInt() &&
+ 0x4C == cmd[3].unsignedToInt()
+ ) {
+ //file 0x09
+ send.Le = 37
+ }
+ }
+ else -> {
+ System.arraycopy(cmd, 0, send.Command, 0, 4)
+ send.Lc = cmd[4].unsignedToInt().toShort()
+ System.arraycopy(cmd, 5, send.DataIn, 0, send.Lc.toInt())
+ if (cmd.size > 5 + send.Lc) {
+ send.Le = cmd[5 + send.Lc].unsignedToInt().toShort()
+ }
+ }
+ }
+ var ret = picc!!.sendIsoCommand(0.toByte(), send, resp)
+ if (ret == 0) {
+ if (resp.SWA.unsignedToInt() == 0x61 &&
+ resp.SWB.unsignedToInt() > 0
+ ) {
+ var recv = ByteArray(resp.LenOut.toInt())
+ System.arraycopy(resp.DataOut, 0, recv, 0, resp.LenOut.toInt())
+ while (true) {
+ val innercmd = ByteArray(5)
+ innercmd[0] = 0x0
+ innercmd[1] = 0xC0.toByte()
+ innercmd[2] = 0x0
+ innercmd[3] = 0x0
+ innercmd[4] = resp.SWB
+ System.arraycopy(innercmd, 0, send.Command, 0, 4)
+ send.Le = innercmd[4].unsignedToInt().toShort()
+ send.Lc = 0
+ ret = picc!!.sendIsoCommand(0.toByte(), send, resp)
+ if (ret == 0) {
+ if (resp.SWA.unsignedToInt() == 0x61 &&
+ resp.SWB.unsignedToInt() > 0
+ ) {
+ val tmp = ByteArray(resp.LenOut.toInt() + recv.size)
+ System.arraycopy(recv, 0, tmp, 0, recv.size)
+ System.arraycopy(resp.DataOut, 0, tmp, recv.size, resp.LenOut.toInt())
+ recv = tmp
+ continue
+ } else {
+ val tmp = ByteArray(resp.LenOut.toInt() + recv.size + 2)
+ System.arraycopy(recv, 0, tmp, 0, recv.size)
+ System.arraycopy(resp.DataOut, 0, tmp, recv.size, resp.LenOut.toInt())
+ tmp[tmp.size - 2] = resp.SWA
+ tmp[tmp.size - 1] = resp.SWB
+ recv = tmp
+ return ApduResponse(recv)
+ }
+ } else {
+ throw CardlibValueError("交互失败,错误码=$ret")
+ }
+ }
+ } else {
+ val recv = ByteArray(resp.LenOut + 2)
+ System.arraycopy(resp.DataOut, 0, recv, 0, resp.LenOut.toInt())
+ recv[resp.LenOut.toInt()] = resp.SWA
+ recv[resp.LenOut + 1] = resp.SWB
+ return ApduResponse(recv)
+ }
+ }
+ LogUtil.d(TAG, "A711Reader cpuApdu error,ret=$ret")
+ throw CardlibValueError("交互失败,错误码=$ret")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/EpayCardlib.kt b/app/src/main/java/com/supwisdom/epaycard/EpayCardlib.kt
new file mode 100644
index 0000000..6c68cb9
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/EpayCardlib.kt
@@ -0,0 +1,45 @@
+package com.supwisdom.epaycard
+
+import com.supwisdom.exception.CardNotFoundError
+import com.supwisdom.exception.CardlibInitError
+import com.supwisdom.exception.CardlibValueError
+import com.supwisdom.utils.decodeHex
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class EpayCardlib {
+ private var reader = DaliReader()
+
+ @Throws(CardlibInitError::class)
+ fun init() {
+ reader.init()
+ }
+
+ @Throws(CardNotFoundError::class)
+ fun requestCard(): String {
+ return reader.requestCard()
+ }
+
+ @Throws(CardlibValueError::class)
+ fun readCard(): CardBaseInfoBean {
+ selectADF()
+ return readBaseInfo()
+ }
+
+ private fun selectADF() {
+ val res = reader.cpuApdu("00A40000023F00".decodeHex())
+ if (!res.isOK()) {
+ throw CardlibValueError("选应用错误:${res.swToString()}")
+ }
+ }
+
+ private fun readBaseInfo(): CardBaseInfoBean {
+ val res = reader.cpuApdu("00B09500".decodeHex())
+ if (!res.isOK()) {
+ throw CardlibValueError("读基本信息错误:${res.swToString()}")
+ }
+ return CardBaseInfoBean(res.data)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardNotFoundError.kt b/app/src/main/java/com/supwisdom/exception/CardNotFoundError.kt
new file mode 100644
index 0000000..43d882c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardNotFoundError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardNotFoundError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardPayCancelFailError.kt b/app/src/main/java/com/supwisdom/exception/CardPayCancelFailError.kt
new file mode 100644
index 0000000..4ab662e
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardPayCancelFailError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayCancelFailError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardPayFailError.kt b/app/src/main/java/com/supwisdom/exception/CardPayFailError.kt
new file mode 100644
index 0000000..558562b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardPayFailError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayFailError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardlibInitError.kt b/app/src/main/java/com/supwisdom/exception/CardlibInitError.kt
new file mode 100644
index 0000000..7404615
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardlibInitError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardlibInitError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardlibValueError.kt b/app/src/main/java/com/supwisdom/exception/CardlibValueError.kt
new file mode 100644
index 0000000..b069e0b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardlibValueError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardlibValueError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/HeartBeatError.kt b/app/src/main/java/com/supwisdom/exception/HeartBeatError.kt
new file mode 100644
index 0000000..b1b4852
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/HeartBeatError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class HeartBeatError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/SysParaError.kt b/app/src/main/java/com/supwisdom/exception/SysParaError.kt
new file mode 100644
index 0000000..3d3c073
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/SysParaError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class SysParaError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/TransdtlUploadError.kt b/app/src/main/java/com/supwisdom/exception/TransdtlUploadError.kt
new file mode 100644
index 0000000..4064c79
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/TransdtlUploadError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class TransdtlUploadError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/WhiteListError.kt b/app/src/main/java/com/supwisdom/exception/WhiteListError.kt
new file mode 100644
index 0000000..5204298
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/WhiteListError.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class WhiteListError : Exception {
+ constructor(message: String, ex: Exception) {
+ Exception(message + ex.message)
+ }
+
+ constructor(message: String) {
+ Exception(message)
+ }
+
+ constructor(ex: Exception) {
+ Exception(ex.message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/AuthEpay.kt b/app/src/main/java/com/supwisdom/service/AuthEpay.kt
index 185c534..a2a3799 100644
--- a/app/src/main/java/com/supwisdom/service/AuthEpay.kt
+++ b/app/src/main/java/com/supwisdom/service/AuthEpay.kt
@@ -1,11 +1,14 @@
package com.supwisdom.service
+import com.supwisdom.bean.AuthRetBean
+import com.supwisdom.utils.PublicDef
+
/**
** create by zzq on 2019/7/23
** @desc
**/
class AuthEpay {
- fun login() {
-
+ fun login(): AuthRetBean {
+ return AuthRetBean(PublicDef.ERROR, "未实行")
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt b/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt
index 6a4d21f..17cb4a6 100644
--- a/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt
+++ b/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt
@@ -4,6 +4,10 @@
import com.supwisdom.activities.YktSession
import com.supwisdom.entity.TransdtlOfflineRecord
import com.supwisdom.entity.TransdtlOnlineRecord
+import com.supwisdom.exception.HeartBeatError
+import com.supwisdom.exception.SysParaError
+import com.supwisdom.exception.TransdtlUploadError
+import com.supwisdom.exception.WhiteListError
import com.supwisdom.okhttp.WebParams
import com.supwisdom.utils.DateUtil
@@ -13,6 +17,8 @@
**/
class EpayApiImpl : APIInterface {
private val pos = SPApplication.getInstance().getPos()
+
+ @Throws(HeartBeatError::class)
override fun heartBeat() {
val dyRecord = pos.getDynamicPara()
val params = WebParams()
@@ -29,6 +35,7 @@
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
+ @Throws(SysParaError::class)
override fun downloadSyspara(paraverno: Int, paragroupid: Int) {
val dyRecord = pos.getDynamicPara()
val params = WebParams()
@@ -40,6 +47,7 @@
val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/systempara", "", params)
}
+ @Throws(WhiteListError::class)
override fun downloadWhitelist(maxCardverno: String) {
val params = WebParams()
params.setParameter("devphyid", pos.getConfigPara()!!.devphyid)
@@ -49,6 +57,7 @@
val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/whitelist", "", params)
}
+ @Throws(TransdtlUploadError::class)
override fun uploadTransdtl(record: TransdtlOnlineRecord) {
val params = WebParams()
params.setParameter("devphyid", record.devphyid)
@@ -58,6 +67,7 @@
val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/paycancel", "", params)
}
+ @Throws(TransdtlUploadError::class)
override fun uploadTransdtl(record: TransdtlOfflineRecord) {
val params = WebParams()
params.setParameter("devphyid", record.devphyid)
diff --git a/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt b/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt
index 63a23ba..5ae8a0c 100644
--- a/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt
+++ b/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt
@@ -31,7 +31,7 @@
@Volatile
private var connectDoing: Boolean = false
private var webSocket: Future<WebSocket>? = null
- private var reLinkCnt: Long = 0
+ private var reLinkCnt: Int = 0
private var clientID = ""
@Volatile
private var hasRecv: Boolean = false
@@ -51,7 +51,7 @@
}
}
}
- clientID = SPApplication.getInstance().getPos().getConfigPara().getDevphyid()
+ clientID = SPApplication.getInstance().getPos().getConfigPara()!!.devphyid!!
}
fun setHandler(handler: Handler) {
@@ -127,7 +127,7 @@
// val loginStr = getLoginString()
// webSocket.send(loginStr)
webSocket.stringCallback = WebSocket.StringCallback { s ->
-// if (!CommonUtil.isEmpty(s)) {
+ // if (!CommonUtil.isEmpty(s)) {
// try {
// val retBean = GsonUtil.GsonToBean(s, WebsocketRetBean::class.java)
// if (retBean.getRetcode() === PublicDef.SUCCESS) {
diff --git a/app/src/main/java/com/supwisdom/utils/CommonUtil.kt b/app/src/main/java/com/supwisdom/utils/CommonUtil.kt
index 91af8f7..5891662 100644
--- a/app/src/main/java/com/supwisdom/utils/CommonUtil.kt
+++ b/app/src/main/java/com/supwisdom/utils/CommonUtil.kt
@@ -50,6 +50,18 @@
return commTime
}
+ fun getSerialNumber(): String? {
+ try {
+ val c = Class.forName("android.os.SystemProperties")
+ val get = c.getMethod("get", String::class.java)
+ return get.invoke(c, "ro.product.firmware") as String
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+
+ return null
+ }
+
fun YuanToFen(yuan: Double): Int {
return Math.round(yuan * 100).toInt()
}
diff --git a/app/src/main/java/com/supwisdom/utils/PublicDef.kt b/app/src/main/java/com/supwisdom/utils/PublicDef.kt
index 14fc606..7f1204d 100644
--- a/app/src/main/java/com/supwisdom/utils/PublicDef.kt
+++ b/app/src/main/java/com/supwisdom/utils/PublicDef.kt
@@ -21,6 +21,12 @@
/**************************************************************/
/*************************handler 状态码***********************/
+ const val MSG_CARD_PAYING = 10
+ const val MSG_CARD_PAY_FAIL = 11
+ const val MSG_CARD_PAY_SUC = 12
+ const val MSG_CARD_PAY_QUERY = 13
+ const val MSG_CARD_PAYCANCEL_FAIL = 14
+ const val MSG_CARD_PAYCANCEL_SUC = 15
/*************************不能重复*****************************/
/**
* 卡消费标志(1 byte)
@@ -57,4 +63,14 @@
const val DIALOG_TYPE_ORDINARY_CONSUME = 7
const val DIALOG_TYPE_DEPOSIT = 8
const val DIALOG_TYPE_NSD_CONFIG = 9
+
+ /**
+ * 本地全局控制参数
+ */
+ const val CONTROL_TRANSDTLONL_SEQNO = "onlseqno"
+ const val CONTROL_TRANSDTLOFF_SEQNO = "offseqno"
+ const val CONTROL_FIXAMT = "fixamt"
+ const val CONTROL_HAS_REGISTER = "hasregister"
+ const val CONTROL_GATEMODE_FLAG = "gatemodeflag"
+ const val CONTROL_REVENUE_WAY = "revenueway"
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/app_logo.png b/app/src/main/res/drawable-hdpi/app_logo.png
new file mode 100644
index 0000000..b4073ad
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/app_logo.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/consume_middle_background.png b/app/src/main/res/drawable-hdpi/consume_middle_background.png
new file mode 100644
index 0000000..9af8c90
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/consume_middle_background.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/iconerrork.png b/app/src/main/res/drawable-hdpi/iconerrork.png
new file mode 100644
index 0000000..57493fe
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/iconerrork.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/iconfont_del.png b/app/src/main/res/drawable-hdpi/iconfont_del.png
new file mode 100644
index 0000000..6c89d1c
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/iconfont_del.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/loading.png b/app/src/main/res/drawable-hdpi/loading.png
new file mode 100644
index 0000000..c9acbab
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/loading.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/loading_white.png b/app/src/main/res/drawable-hdpi/loading_white.png
new file mode 100644
index 0000000..abfb07f
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/loading_white.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/minus.png b/app/src/main/res/drawable-hdpi/minus.png
new file mode 100644
index 0000000..e672aaf
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/minus.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/minus_click.png b/app/src/main/res/drawable-hdpi/minus_click.png
new file mode 100644
index 0000000..580c410
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/minus_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/pay_fail.png b/app/src/main/res/drawable-hdpi/pay_fail.png
new file mode 100644
index 0000000..9b0ac71
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/pay_fail.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/pay_success.png b/app/src/main/res/drawable-hdpi/pay_success.png
new file mode 100644
index 0000000..62ed4e2
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/pay_success.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/scrollbar.xml b/app/src/main/res/drawable-hdpi/scrollbar.xml
new file mode 100644
index 0000000..8289699
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/scrollbar.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#505050"
+ android:endColor="#C0C0C0"
+ android:angle="0" />
+ <corners android:radius="0dp" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/scrollbar_bg.xml b/app/src/main/res/drawable-hdpi/scrollbar_bg.xml
new file mode 100644
index 0000000..2a31b9e
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/scrollbar_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#ffff792a"
+ android:endColor="#ffff792a"
+ android:angle="0" />
+ <corners android:radius="4dp" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/user_logo.png b/app/src/main/res/drawable-hdpi/user_logo.png
new file mode 100644
index 0000000..138412d
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/user_logo.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/user_logo_default.png b/app/src/main/res/drawable-hdpi/user_logo_default.png
new file mode 100644
index 0000000..2ae652f
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/user_logo_default.png
Binary files differ
diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml
new file mode 100644
index 0000000..c89c3e3
--- /dev/null
+++ b/app/src/main/res/layout/activity_splash.xml
@@ -0,0 +1,48 @@
+<!--
+android:gravity是对元素本身说的,元素本身的文本显示在什么地方靠着换个属性设置,不过不设置默认是在左侧的。
+android:layout_gravity是相对与它的父元素说的,说明元素显示在父元素的什么位置
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/LinearLayout01"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+ <!--
+ android:scaleType是控制图片如何resized/moved来匹对ImageView的size
+ CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
+ -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:gravity="center|center"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/wordpress_logo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:scaleType="centerInside"
+ android:src="@drawable/app_logo"></ImageView>
+ <!--
+ android:typeface 字体风格
+ -->
+ <TextView
+ android:id="@+id/versionNumber"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:gravity="bottom"
+ android:shadowColor="#FFFFFF"
+ android:shadowDx="0"
+ android:shadowDy="2"
+ android:shadowRadius="1"
+ android:text="0.0.0"
+ android:textColor="@color/pos_theme_color"
+ android:textSize="@dimen/main_caption_size"
+ android:typeface="serif" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 44fc515..c26513d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -58,10 +58,10 @@
<string name="title_activity_qrcamera">扫码</string>
<string name="title_activity_splash">树维pos</string>
<string name="waiting_msg">正在识别,请稍后…</string>
- <string name="username">姓 名</string>
+ <string name="username">姓 名</string>
<string name="userStuEmpNo">学工号</string>
<string name="userExpireDate">有效期</string>
- <string name="userBalance">余 额</string>
+ <string name="userBalance">余 额</string>
<string name="consumeAmount">消费额(元)</string>
<string name="title_activity_consume_cancel">消费撤销</string>
<string name="title_activity_update_blacklist">更新黑名单</string>