数据同步接口定义
diff --git a/build.gradle b/build.gradle
index d9f0ca9..a0654a6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -59,6 +59,7 @@
implementation 'org.springframework.social:spring-social-web:1.1.6.RELEASE'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
+ implementation 'commons-codec:commons-codec:1.12'
implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery:2.1.2.RELEASE'
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java b/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java
index c6788d8..3ccb2a7 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java
@@ -12,7 +12,11 @@
public static final int SYSPARAID_NO1 = 1; //系统默认最大余额限制的ID
public static final int SYSPARAID_NO2 = 2; //paraid=2
- public static final int SYSPARAID_NO3 = 3; //用户过期时间,单位秒
+
+ public static final int SYSPARAID_NO2019 = 2019; //与卡管系统对接的应用ID
+ public static final int SYSPARAID_NO2020 = 2020; //与卡管系统对接的应用appkey
+ public static final int SYSPARAID_NO2021 = 2021; //与卡管系统对接的业务参数deskey
+
public static final double SYSPARA_NO1_DEFAULT = 10000.0; // 系统默认最大余额限制
}
diff --git a/src/main/java/com/supwisdom/dlpay/util/DESedeUtil.java b/src/main/java/com/supwisdom/dlpay/util/DESedeUtil.java
new file mode 100644
index 0000000..0d0e4cf
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/util/DESedeUtil.java
@@ -0,0 +1,107 @@
+package com.supwisdom.dlpay.util;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.StringUtils;
+
+import javax.crypto.*;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * 加密/解密工具类
+ */
+public class DESedeUtil {
+ /**
+ * 加密工具类唯一实例
+ */
+ private static DESedeUtil instance = null;
+ /**
+ *
+ */
+ private Cipher cipher;
+ /**
+ *
+ */
+ private SecretKey secretKey;
+ /**
+ *
+ */
+ private IvParameterSpec ivSpec;
+
+ /**
+ * 初始化、创建密钥数据
+ *
+ * @throws NoSuchPaddingException
+ * @throws NoSuchAlgorithmException
+ */
+ private DESedeUtil(String deskey) throws NoSuchAlgorithmException, NoSuchPaddingException {
+ byte[] keyData = Base64.decodeBase64(deskey);
+ String fullAlg = "DESede/CBC/PKCS5Padding";
+ cipher = Cipher.getInstance(fullAlg);
+ int blockSize = cipher.getBlockSize();
+ byte[] iv = new byte[blockSize];
+ for (int i = 0; i < blockSize; ++i) {
+ iv[i] = 0;
+ }
+ secretKey = new SecretKeySpec(keyData, StringUtils.substringBefore(fullAlg, "/"));
+ ivSpec = new IvParameterSpec(iv);
+ }
+
+ /**
+ * 获取唯一实例
+ *
+ * @return
+ * @throws NoSuchPaddingException
+ * @throws NoSuchAlgorithmException
+ */
+ public static DESedeUtil getInstance(String deskey) throws NoSuchAlgorithmException, NoSuchPaddingException {
+ if (null == instance) {
+ synchronized (DESedeUtil.class) {
+ if (null == instance) {
+ instance = new DESedeUtil(deskey);
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * 加密
+ *
+ * @param s 待加密字符串
+ * @return 返回BASE64编码加密字符串
+ * @throws InvalidAlgorithmParameterException
+ * @throws InvalidKeyException
+ * @throws BadPaddingException
+ * @throws IllegalBlockSizeException
+ * @throws UnsupportedEncodingException
+ */
+ public String encode(String s) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
+ byte[] cipherBytes = cipher.doFinal(s.getBytes("UTF-8"));
+ return new String(Base64.encodeBase64(cipherBytes));
+ }
+
+ /**
+ * 解密
+ *
+ * @param s 待解密字符串
+ * @return 返回明文
+ * @throws InvalidAlgorithmParameterException
+ * @throws InvalidKeyException
+ * @throws BadPaddingException
+ * @throws IllegalBlockSizeException
+ * @throws UnsupportedEncodingException
+ */
+ public String decode(String s) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
+ byte[] resultBytes = cipher.doFinal(Base64.decodeBase64(s));
+ return new String(resultBytes, "UTF-8");
+ }
+
+}
+
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt b/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
index 447a3f2..5568b6f 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
@@ -1,8 +1,11 @@
package com.supwisdom.dlpay.api.bean
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
import com.supwisdom.dlpay.exception.RequestParamCheckException
import com.supwisdom.dlpay.framework.util.*
import com.supwisdom.dlpay.util.ConstantUtil
+import com.supwisdom.dlpay.util.DESedeUtil
// ============================ USER ============================ //
class OpenUserParam : APIRequestParam() {
@@ -355,3 +358,53 @@
}
+class DaliDatasyncParam {
+ var app_id: String = ""
+ var data: String = ""
+ var count: Int = 0
+ var timestamp: String = ""
+ var sign_type: String = ""
+ var sign: String = ""
+
+ fun checkParam(): Boolean {
+ if (StringUtil.isEmpty(app_id)) throw RequestParamCheckException(2000, "请求参数错误[应用ID为空]")
+ if (StringUtil.isEmpty(data)) throw RequestParamCheckException(2000, "请求参数错误[业务参数报文为空]")
+ if (null == count || count < 1) throw RequestParamCheckException(2000, "请求参数错误[业务明细至少有一条]")
+ if (!DateUtil.checkDatetimeValid(timestamp, DateUtil.DATETIME_FMT)) throw RequestParamCheckException(2000, "请求参数错误[时间戳]")
+ if (StringUtil.isEmpty(sign_type) || !"HmacSHA256".equals(sign_type, true)) throw RequestParamCheckException(2000, "请求参数错误[签名算法]")
+ if (StringUtil.isEmpty(sign)) throw RequestParamCheckException(2000, "请求参数错误[签名为空]")
+
+ return true
+ }
+
+ fun checkSign(key: String): Boolean {
+ val signData = "app_id=$app_id&count=$count&data=$data×tamp=$timestamp"
+ return sign.equals(HmacUtil.HMACSHA256(signData, key), true)
+ }
+
+ fun decData(deskey: String): ArrayList<DaliDatasyncDetail> {
+ try {
+ val listType = object : TypeToken<ArrayList<ConsumeFeetype>>() {}.type
+ val decstr = DESedeUtil.getInstance(deskey).decode(data)
+ return Gson().fromJson(decstr, listType)
+ } catch (e: Exception) {
+ throw RequestParamCheckException(1001, "数据解密失败!")
+ }
+ }
+
+}
+
+class DaliDatasyncDetail {
+ var cardno: String = ""
+ var cardphyid: String = ""
+ var expiredate: String = ""
+ var cardstatus: String = ""
+ var bankcardno: String? = null
+ var username: String = ""
+ var idtype: String = ""
+ var idno: String = ""
+ var mobile: String? = null
+ var email: String? = null
+}
+
+
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt
new file mode 100644
index 0000000..9756233
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt
@@ -0,0 +1,63 @@
+package com.supwisdom.dlpay.api.controller
+
+import com.supwisdom.dlpay.api.bean.DaliDatasyncParam
+import com.supwisdom.dlpay.exception.RequestParamCheckException
+import com.supwisdom.dlpay.framework.ResponseBodyBuilder
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.framework.util.SysparaUtil
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.ResponseEntity
+import org.springframework.web.bind.annotation.*
+
+@RequestMapping("/api/common")
+class DaliDatasyncApiController {
+ @Autowired
+ lateinit var systemUtilService: SystemUtilService
+
+ /**
+ * ============================================================================
+ * 大理卡管系统推送市民卡信息同步接口
+ * ============================================================================
+ * */
+ @PostMapping("/datasync")
+ @ResponseBody
+ fun daliDatasync(@RequestBody param: DaliDatasyncParam): ResponseEntity<Any> {
+ try {
+ param.checkParam()
+ val appid = systemUtilService.getSysparaValue(SysparaUtil.SYSPARAID_NO2019)
+ val appkey = systemUtilService.getSysparaValue(SysparaUtil.SYSPARAID_NO2020)
+ val deskey = systemUtilService.getSysparaValue(SysparaUtil.SYSPARAID_NO2021)
+ if (StringUtil.isEmpty(appid) || StringUtil.isEmpty(appkey) || StringUtil.isEmpty(deskey)) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(1000, "系统参数未配置"))
+ } else if (appid != param.app_id) {
+ throw RequestParamCheckException(2000, "请求参数错误[应用ID错误]")
+ }
+ if (!param.checkSign(appkey)) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(2001, "签名错误"))
+ }
+
+ val datalist = param.decData(deskey)
+ if (param.count != datalist.size) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(2002, "请求参数错误[数据条数不匹配]"))
+ }
+
+ datalist.forEach {
+ TODO("更新数据逻辑")
+ }
+
+ return return ResponseEntity.ok(mapOf("retcode" to "0000", "retmsg" to "SUCCESS"))
+ } catch (ex: RequestParamCheckException) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(ex.errCode, ex.message ?: "请求参数错误"))
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(4000, "系统处理错误"))
+ }
+ }
+
+}
\ No newline at end of file