| @@ -40,11 +40,6 @@ | |||
| <artifactId>alipay-easysdk</artifactId> | |||
| <version>2.2.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.iformall</groupId> | |||
| <artifactId>mallinkAdmin</artifactId> | |||
| <version>1.0</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -9,7 +9,7 @@ public enum EnumCarVendor { | |||
| CAR_NOTFOUND(0, "无",false), | |||
| CAR_ETCP(1, "ETCP",false), | |||
| CAR_TJD(2, "TJD",false),// 【接口不支持未接通,不能使用】 | |||
| CAR_DAHUA(3, "DAHUA",false),// 【接口不支持未接通,不能使用】 | |||
| CAR_DAHUA(3, "DAHUA",false),//大华 | |||
| CAR_SHANGAN(4, "ShangAn",false),// 【接口不支持未接通,不能使用】 | |||
| CAR_BOLINK(5, "BoLink",false),// 【接口不支持未接通,不能使用】 | |||
| CAE_CYF(6,"CYF",false),// 【接口不支持未接通,不能使用】 | |||
| @@ -342,7 +342,9 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ | |||
| }else if(EnumPayWay.PAY_WAY_TT.getCode().equals(payOrder.getPayVendor()) | |||
| && EnumPayMchType.DIRECT.getCode().equals(payOrder.getMchType()) | |||
| && !sharingOrder.getMerchantId().equals(wxComposeChildOrderShare.getMerchantId()) | |||
| && EnumTtPayChannel.ALI_PAY.getCode().equals(payOrder.getTtPayWay())){ | |||
| // && EnumTtPayChannel.ALI_PAY.getCode().equals(payOrder.getTtPayWay()) | |||
| ){ | |||
| //todo 微信支付最大分账30% 限制 | |||
| //抖音 直连 多商户 支付宝支付 进件支付宝 分账 否则记账 | |||
| JSONObject jo = new JSONObject(); | |||
| jo.put("type",EnumProfitPaymentReceiverType.getEnum(receiver.getReceiverType()).getMessage()); | |||
| @@ -1,30 +1,116 @@ | |||
| package com.iformall.service.park.impl.dahua; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Qualifier; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Service; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONArray; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.common.IdWorker; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.domain.po.WxCUserBasicInfo; | |||
| import com.iformall.domain.po.WxCarJSOrder; | |||
| import com.iformall.domain.po.WxCoupon; | |||
| import com.iformall.domain.po.WxPark; | |||
| import com.iformall.domain.vo.WxCouponOrderCarCVo; | |||
| import com.iformall.domain.vo.WxParkCouponConfig; | |||
| import com.iformall.enums.EnumCarVendor; | |||
| import com.iformall.enums.EnumCouponUnit; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.mapper.WxCarJSOrderMapper; | |||
| import com.iformall.service.WxParkService; | |||
| import com.iformall.service.park.ParkAdapterService; | |||
| import com.iformall.service.park.entity.ParkCreatePayOrder; | |||
| import com.iformall.service.park.entity.ParkNotifyPaid; | |||
| import com.iformall.service.park.entity.ParkPaidNotifyResult; | |||
| import com.iformall.service.park.entity.ParkStopFee; | |||
| import com.iformall.service.park.impl.BaseParkService; | |||
| import com.iformall.service.park.impl.util.ParkHelper; | |||
| import com.iformall.service.park.utils.ParkCacheUtils; | |||
| import com.iformall.utils.RedisCacheUtils; | |||
| import com.iformall.utils.RedisLock; | |||
| /** | |||
| * | |||
| * https://www.cloud-dahua.com FMLK2023/fmlk2023 | |||
| */ | |||
| @Service | |||
| public class DaHuaParkService extends BaseParkService implements ParkAdapterService { | |||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||
| @Autowired | |||
| ParkHelper parkHelper; | |||
| @Autowired | |||
| @Qualifier("objectCommonRedisTemplate") | |||
| RedisTemplate<String, Object> redisTemplate; | |||
| @Autowired | |||
| RedisLock redisLock; | |||
| @Autowired | |||
| WxCarJSOrderMapper wxCarJSOrderMapper; | |||
| DaHuaUtil dahua = new DaHuaUtil(); | |||
| private String getCacheToken(WxPark park) { | |||
| String token = RedisCacheUtils.getCacheString(redisTemplate, "carStop:dahuatoken:"+park.getId()); | |||
| if (StringUtils.isBlank(token)) { | |||
| String lockKey = "carStop:dahuatokenlock:"+park.getTenantId(); | |||
| long time = System.currentTimeMillis() + 2000; | |||
| String timeStr = String.valueOf(time); | |||
| if (redisLock.lock2(lockKey, timeStr)) { | |||
| token = dahua.getToken(park); | |||
| if (!StringUtils.isBlank(token)) { | |||
| setCacheToken(park, token); | |||
| } | |||
| redisLock.unlock(lockKey, timeStr); | |||
| } else { | |||
| try { | |||
| Thread.sleep(2000); | |||
| } catch (InterruptedException e) { | |||
| e.printStackTrace(); | |||
| }finally { | |||
| redisLock.unlock(lockKey, timeStr); | |||
| } | |||
| } | |||
| } | |||
| return RedisCacheUtils.getCacheString(redisTemplate, "carStop:dahuatoken:"+park.getId()); | |||
| } | |||
| private void setCacheToken(WxPark park,String token) { | |||
| RedisCacheUtils.cache(redisTemplate, "carStop:dahuatoken:"+park.getId(), token, 3600); | |||
| } | |||
| /** | |||
| * 先去捷顺注册,调用登陆获取令牌,然后根据令牌调用别的接口 | |||
| * http://ap.jieshun.cn:9088/apply/ 注册信息地址 fumao/iformall2020 | |||
| * | |||
| * 捷顺商户平台:http://merchant.jslife.com.cn/merchant/index.html#/auth/login | |||
| * 捷顺门店平台:http://merchant.jslife.com.cn/store/index.html#/auth/login | |||
| * 门店商户号 000000008032172000003 密码 ycHqp61Acudxz | |||
| * | |||
| * | |||
| * API对接注意事项: | |||
| 1、token有效期两个小时,每两小时内登录一次获取token,调业务接口不需要频繁登录用,建议获取一次token存本地缓存,之后从本地获取,两小时内刷新一次, | |||
| 为避免调业务接口时刚好token被刷新,导致token失效(无效的令牌或令牌已过期),可以做下容错,重新登录获取token或用最新token重新调业务接口。 | |||
| 2、token是和ip是一对一绑定,新的ip服务器调捷顺的接口会出现ip不合法,需把ip提供捷顺方,添加白名单。多个服务调捷顺接口共用一个ip情况下,只能共用一套登录获取token机制,各自登录会冲突。 | |||
| 3、所有接口要带车牌的一律带横杠。格式如:粤-B12345。 | |||
| 4、无效的数据签名是指sn加密方式不对。sn加密方式是对p+signkey进行Md5加密,加密后的字符串大写。 | |||
| */ | |||
| @Override | |||
| public ResultData parkInitConfig(WxPark park) throws Exception { | |||
| @@ -33,64 +119,202 @@ public class DaHuaParkService extends BaseParkService implements ParkAdapterServ | |||
| } | |||
| @Override | |||
| public String initLogin(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) { | |||
| public String initLogin(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) throws Exception{ | |||
| return null; | |||
| } | |||
| @Override | |||
| public String bindCar(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) { | |||
| return member.getId().toString(); | |||
| public String bindCar(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) throws Exception{ | |||
| return "jieshunV2"; | |||
| } | |||
| @Override | |||
| public void unbindCar(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) { | |||
| public void unbindCar(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) throws Exception{ | |||
| } | |||
| /** | |||
| * 每一次查询都会产生订单,然后根据订单号查询 | |||
| */ | |||
| @Override | |||
| public ParkStopFee carStopFee(Map<String, String> paramMap, WxPark park,String carNumber) { | |||
| return dahuaCarStopFee(paramMap, park,carNumber); | |||
| public ParkStopFee carStopFee(Map<String, String> paramMap, WxPark park,String carNumber) throws Exception{ | |||
| return jieshunCarStopFee(paramMap, park,carNumber); | |||
| } | |||
| private ParkStopFee dahuaCarStopFee(Map<String, String> paramMap, WxPark park,String carNumber) { | |||
| String result = DaHuaUtil.plateCharge(carNumber, park.getParkId()); | |||
| logger.info("大华查询车辆费用接口返回值:{}", result); | |||
| JSONObject jsonObject = JSONObject.parseObject(result); | |||
| String code = jsonObject.getString("code"); | |||
| if (!code.equals(DaHuaUtil.SUCCESS_CODE)) { | |||
| throw new MallinkException(ErrorCode.CAR_VENDOR_NOT_SUPPORT.getCode(), "停车费获取失败"); | |||
| private ParkStopFee jieshunCarStopFee(Map<String, String> paramMap, WxPark park,String carNumber) throws Exception{ | |||
| //下订单; | |||
| String retCode = dahua.createOrder(park, carNumber, getCacheToken(park)); | |||
| if (StringUtils.isBlank(retCode)) { | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "dahua createOrder error. has no result"); | |||
| } | |||
| Object data = jsonObject.get("data"); | |||
| JSONObject result = JSON.parseObject(retCode); | |||
| if (!result.getBoolean("success") ) { | |||
| String message = result.getString("errMsg"); | |||
| throw new MallinkException(result.getInteger("code"), "dahua createOrder error."+message); | |||
| } | |||
| JSONObject arrays = result.getJSONObject("data"); | |||
| if (null == arrays || arrays.size() == 0) { | |||
| throw new MallinkException(result.getInteger("resultCode"), "jieshun createOrder error. no order result"+carNumber); | |||
| } | |||
| // JSONObject attribute = arrays.getJSONObject(0).getJSONObject("attributes"); | |||
| // Double totalFee = attribute.getDouble("totalFee"); | |||
| // String appId = "wx24b70f0ad2a9a89a"; | |||
| // String parkOrderId = attribute.getString("orderNo"); | |||
| // Integer freeMinute = (Integer)park.getVendorParamsByKey("freeMinute"); | |||
| // if (totalFee <= 0 ) { | |||
| // String _createTime = attribute.getString("startTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss” | |||
| // String _endTime = attribute.getString("endTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss” | |||
| // String msg = attribute.getString("retmsg"); | |||
| // if (!StringUtils.isBlank(msg)) { | |||
| // if (msg.contains("未入场")) { | |||
| // return new ParkStopFee(null,jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime), | |||
| // "0.00",appId,"payPath",null,msg,null); | |||
| // }else { | |||
| // //0元订单结清,查询是否用过打折方案,如果用过,则需要调用接口结清订单 | |||
| // Integer used = ParkCacheUtils.getCarCouponUseCacheLock(redisTemplate, EnumCarVendor.CAR_JIESHUN_V2.getMessage(), carNumber); | |||
| // if (null == used || (null != used && used.intValue() < 1)) { | |||
| // //未使用停车券 | |||
| // return new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime), | |||
| // "0.00",appId,"payPath",null,msg,null); | |||
| // }else { | |||
| // return new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime), | |||
| // "0.00",appId,"payPath",null,msg,"用券抵扣后账单为0,获得"+freeMinute+"分钟免费出场时间"); | |||
| // } | |||
| // } | |||
| // } | |||
| // } | |||
| // | |||
| // | |||
| // String ret = jieshun.getCarStopFee(park, parkOrderId, getCacheToken(park)); | |||
| // JSONObject retObj = JSON.parseObject(ret); | |||
| // if (retObj.getIntValue("resultCode") == 0){ | |||
| // JSONArray retArrays = retObj.getJSONArray("dataItems"); | |||
| // if (null == retArrays || retArrays.size() == 0 ) { | |||
| // throw new MallinkException(result.getInteger("resultCode"), "jieshun getCarStopFee error. no order result"+carNumber); | |||
| // } | |||
| // | |||
| // JSONObject retObject = retArrays.getJSONObject(0).getJSONObject("attributes"); | |||
| // String createTime = retObject.getString("startTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss” | |||
| // String endTime = retObject.getString("endTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss” | |||
| // String payPath = "pages/thirdPayOrderByNo/payOrder?orderNo="+parkOrderId+"&freeMinute="+freeMinute; | |||
| // //String payPath = "pages/thirdPayOrder/payOrder?carNo="+jieshun.handleCarNumber(carNumber)+"&parkCode="+park.getParkingId(); | |||
| // return new ParkStopFee(parkOrderId,jieshun.utcToLocal(createTime),jieshun.utcToLocal(endTime), | |||
| // String.valueOf(retObject.getDouble("totalFee")),appId,payPath,null,null,"请支付后"+freeMinute+"分钟内离场"); | |||
| // }else { | |||
| // logger.error("jieshunCarStopFee error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),ret); | |||
| // String msg = retObj.getString("message"); | |||
| // throw new MallinkException(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "停车费获取失败:"+msg); | |||
| // } | |||
| return null; | |||
| } | |||
| /** | |||
| * 使用3.8打折方案,3.9有限制如果领券了之后未使用,不能再次领券。导致出现异常之后,用户永远无法使用优惠券。 | |||
| * @return | |||
| */ | |||
| @Override | |||
| public ResultData useCoupon(Map<String, String> paramMap, WxPark park, WxCouponOrderCarCVo userCar,WxCoupon coupon,String carNumber) { | |||
| return new ResultData(); | |||
| public ResultData useCoupon(Map<String, String> paramMap, WxPark park, WxCouponOrderCarCVo userCar,WxCoupon coupon,String carNumber) throws Exception{ | |||
| if (null == userCar) { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"当前用户未查询到优惠券!"); | |||
| } | |||
| if (StringUtils.isBlank(userCar.getCUserPhone())) { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"当前用户未查询到手机号!"+userCar.getcUserId()); | |||
| } | |||
| Map<String,String> valueMap = WxParkCouponConfig.parseValue(userCar.getVendorParams()); | |||
| if (null == valueMap) { | |||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券没有关联停车场优惠券配置。"+coupon.getTitle()); | |||
| } | |||
| //String orderNo = paramMap.get("parkOrderId"); | |||
| String planNo = valueMap.get("couponNo"); | |||
| if (StringUtils.isBlank(planNo)) { | |||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券没有关联停车场优惠券配置[planNo]。"+coupon.getTitle()); | |||
| } | |||
| //String ret = jieshun.getCoupon(park, planNo,userCar.getCUserPhone(), getCacheToken(park)); | |||
| //打折登陆验证 | |||
| String ret = dahua.verifyuser(park, getCacheToken(park)); | |||
| logger.info("jieshun verifyuser result:"+ret); | |||
| JSONObject retObj = JSON.parseObject(ret); | |||
| if (retObj.getIntValue("resultCode") == 0){ | |||
| JSONArray verfyArrays = retObj.getJSONArray("dataItems"); | |||
| if (null != verfyArrays && verfyArrays.size() > 0 ) { | |||
| JSONObject verfy = verfyArrays.getJSONObject(0).getJSONObject("attributes"); | |||
| String userId = verfy.getString("userId"); | |||
| //查询门店下打折方案 | |||
| String queryPlanRet = jieshun.querySalePlan(park, getCacheToken(park), userId); | |||
| logger.info("jieshun querySalePlan result:"+queryPlanRet); | |||
| JSONObject queryPlantRetObj = JSON.parseObject(queryPlanRet); | |||
| if (queryPlantRetObj.getIntValue("resultCode") == 0){ | |||
| JSONArray planArrays = queryPlantRetObj.getJSONArray("dataItems"); | |||
| if (null != planArrays && planArrays.size() > 0 ) { | |||
| boolean hasPlan = false; | |||
| for (int i = 0 ; i < planArrays.size(); i++) { | |||
| JSONObject plan = planArrays.getJSONObject(i); | |||
| String planId = plan.getJSONObject("attributes").getString("planId"); | |||
| if (planNo.equals(planId)) { | |||
| hasPlan = true; | |||
| break; | |||
| } | |||
| } | |||
| if (!hasPlan) { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"当前优惠券配置的捷顺编号无效,请联系管理员。"+coupon.getTitle()); | |||
| } | |||
| //使用打折方案 | |||
| String executeRet = jieshun.executediscount(park, planNo, userId, carNumber, getCacheToken(park)); | |||
| logger.info("jieshun executediscount result:"+executeRet); | |||
| JSONObject executeRetObj = JSON.parseObject(executeRet); | |||
| if (executeRetObj.getIntValue("resultCode") == 0){ | |||
| return new ResultData(); | |||
| }else { | |||
| return new ResultData(executeRetObj.getIntValue("resultCode"),"当前用户使用捷顺停打折方案失败。"+executeRetObj.getString("message")); | |||
| } | |||
| }else { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"捷顺查询门店未查询到打折信息,请联系管理员。"+userCar.getcUserId()); | |||
| } | |||
| }else { | |||
| logger.error("jieshun querySalePlan error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),queryPlanRet); | |||
| String msg = queryPlantRetObj.getString("message"); | |||
| return new ResultData(queryPlantRetObj.getIntValue("resultCode"), "捷顺查询门店打折方案失败:"+msg); | |||
| } | |||
| }else { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"捷顺门店账号登陆失败,请联系管理员。"+userCar.getcUserId()); | |||
| } | |||
| }else { | |||
| logger.error("jieshun verifyuser error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),ret); | |||
| String msg = retObj.getString("message"); | |||
| return new ResultData(retObj.getIntValue("resultCode"), "当前用户领用到捷顺停车券失败:"+msg); | |||
| } | |||
| } | |||
| @Override | |||
| public ResultData getParkStatus(WxPark park) { | |||
| return new ResultData(); | |||
| public ParkCreatePayOrder createPayOrder(Map<String, String> paramMap, WxPark park, String carNumber) throws Exception { | |||
| return null; | |||
| } | |||
| @Override | |||
| public boolean ignoreUseCouponCache() { | |||
| return false; | |||
| public ParkPaidNotifyResult notifyPaid(WxPark park,ParkNotifyPaid notifyPaid) throws Exception { | |||
| return null; | |||
| } | |||
| @Override | |||
| public ParkCreatePayOrder createPayOrder(Map<String, String> paramMap, WxPark park, String carNumber) | |||
| throws Exception { | |||
| // TODO Auto-generated method stub | |||
| return null; | |||
| public ResultData getParkStatus(WxPark park) throws Exception{ | |||
| return new ResultData(); | |||
| } | |||
| @Override | |||
| public ParkPaidNotifyResult notifyPaid(WxPark park,ParkNotifyPaid notifyPaid) throws Exception { | |||
| return null; | |||
| public boolean ignoreUseCouponCache() { | |||
| return false; | |||
| } | |||
| } | |||
| @@ -1,54 +1,327 @@ | |||
| package com.iformall.service.park.impl.dahua; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.iformall.utils.AesUtils; | |||
| import com.iformall.utils.HttpUtil; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.domain.po.WxPark; | |||
| import com.iformall.exception.MallinkException; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.apache.http.Consts; | |||
| import org.apache.http.HttpEntity; | |||
| import org.apache.http.HttpResponse; | |||
| import org.apache.http.NameValuePair; | |||
| import org.apache.http.client.entity.UrlEncodedFormEntity; | |||
| import org.apache.http.client.methods.HttpPost; | |||
| import org.apache.http.entity.ContentType; | |||
| import org.apache.http.entity.StringEntity; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import org.apache.http.impl.client.HttpClients; | |||
| import org.apache.http.message.BasicHeader; | |||
| import org.apache.http.message.BasicNameValuePair; | |||
| import org.apache.http.protocol.HTTP; | |||
| import org.apache.http.util.EntityUtils; | |||
| import java.io.IOException; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.net.URLEncoder; | |||
| import java.security.MessageDigest; | |||
| import java.security.NoSuchAlgorithmException; | |||
| import java.text.ParseException; | |||
| import java.text.SimpleDateFormat; | |||
| import java.time.LocalDateTime; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.TimeZone; | |||
| /** | |||
| * 大华 停车管理 | |||
| * @author: furunxin | |||
| * @Date: 2020/7/1 17:16 | |||
| * @Description: 车易付接口对接参数类 | |||
| */ | |||
| public class DaHuaUtil { | |||
| public static final String KEY = "8G5M4Ff9hel6fUA7"; | |||
| public static final String IV = "g8v90drvOmIx1PuR"; | |||
| @Slf4j | |||
| public class DaHuaUtil { | |||
| public static final String URL = "http://47.106.104.196:8025/external/common"; | |||
| public static final String TOKEN_URL = "https://www.cloud-dahua.com/gateway/auth/oauth/token"; | |||
| public static final String CREATE_ORDER = "https://open-pkc.cloud-dahua.com/jsaims/as"; | |||
| public static final String QUERY_ORDER = "http://www.jslife.com.cn/jsaims/as"; | |||
| public static final String GET_COUPON = "https://open-pkc.cloud-dahua.com/openplatform/coupon/v1/grantCoupon"; | |||
| public static final String COUPON_USE = "http://www.jslife.com.cn/jsaims/as"; | |||
| public static final String VERIFY_USER = "http://www.jslife.com.cn/jsaims/as"; | |||
| public static final String QUERY_PLAN = "http://www.jslife.com.cn/jsaims/as"; | |||
| public static final String PLAN_EXECUTE = "http://www.jslife.com.cn/jsaims/as"; | |||
| public static final String SUCCESS_CODE = "0000"; | |||
| /** | |||
| * @description UTC时间转化为本地时间 | |||
| * @Params [utcTime] | |||
| * @return java.util.Date | |||
| * @Author furunxin | |||
| * @Date 2020/7/8 下午12:45 | |||
| **/ | |||
| public static Date utcToLocal(String seconds) throws ParseException { | |||
| String format = "yyyy-MM-dd HH:mm:ss"; | |||
| SimpleDateFormat sdf = new SimpleDateFormat(format); | |||
| Date date=sdf.parse(seconds); | |||
| return date; | |||
| } | |||
| public static String parkInfo(String appId) { | |||
| Map<String, Object> requestParams = new HashMap<>(); | |||
| requestParams.put("method", "parkInfo"); | |||
| return request(requestParams, appId); | |||
| public static String getLocalDate(){ | |||
| LocalDateTime ldt = LocalDateTime.now(); | |||
| DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |||
| String nowDate = ldt.format(dtf); | |||
| return nowDate; | |||
| } | |||
| public static String plateCharge(String carNum, String appId) { | |||
| Map<String, Object> requestParams = new HashMap<>(); | |||
| Map<String, Object> data = new HashMap<>(); | |||
| data.put("carNum", carNum); | |||
| requestParams.put("data", data); | |||
| requestParams.put("method", "plateCharge"); | |||
| return request(requestParams, appId); | |||
| public String getToken(WxPark wxPark) { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| String clientId = vp.getString("clientId"); | |||
| String clientSecret = vp.getString("clientSecret"); | |||
| return getToken(clientId,clientSecret); | |||
| } | |||
| private String getToken(String clientId,String clientSecret) { | |||
| String result = ProcLogin(clientId, clientSecret); | |||
| log.info("dahua token clientId:"+clientId+" clientSecret:"+clientSecret+" result: "+result); | |||
| if (StringUtils.isBlank(result)) { | |||
| return null; | |||
| } | |||
| JSONObject res = JSON.parseObject(result); | |||
| String errorCode = res.getString("error"); | |||
| if (StringUtils.isNotBlank(errorCode)) { | |||
| String msg = res.getString("error_description"); | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),msg); | |||
| } | |||
| return res.getString("access_token"); | |||
| } | |||
| private Map generateMap(String serviceId,Map param) { | |||
| Map map = new HashMap(); | |||
| map.put("serviceId", serviceId); | |||
| map.put("requestType", "DATA"); | |||
| map.put("attributes", param); | |||
| return map; | |||
| } | |||
| public String handleCarNumber(String carNumber) { | |||
| if (carNumber.contains("-")) { | |||
| return carNumber; | |||
| }else { | |||
| carNumber = carNumber.substring(0,1)+"-"+carNumber.substring(1, carNumber.length()); | |||
| return carNumber; | |||
| } | |||
| } | |||
| /** | |||
| * 创建订单 | |||
| * @return | |||
| */ | |||
| public String createOrder(WxPark wxPark,String cardNumber,String token) { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("businesserCode", vp.getString("cid"));//商户编号 | |||
| param.put("parkCode", wxPark.getParkingId()); | |||
| param.put("orderType", "VNP"); | |||
| param.put("carNo", handleCarNumber(cardNumber)); | |||
| Map map = generateMap("3c.pay.createorderbycarno",param); | |||
| log.info("jieshunv2 create order :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(CREATE_ORDER, vp.getString("cid"), map, token,vp.getString("version"),vp.getString("signkey")); | |||
| } | |||
| /** | |||
| * 查询停车费 | |||
| **/ | |||
| public String getCarStopFee(WxPark wxPark,String orderNo,String token){ | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("orderNo", orderNo);//商户编号 | |||
| Map map = generateMap("3c.pay.queryorder",param); | |||
| log.info("jieshunv2 getCarStopFee :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(QUERY_ORDER, vp.getString("cid"), map, token,vp.getString("version"),vp.getString("signkey")); | |||
| } | |||
| /** | |||
| * 打折登陆验证 | |||
| */ | |||
| public String verifyuser(WxPark wxPark,String token) { | |||
| try { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("userCode", vp.get("loginUser"));//商户编号 | |||
| MessageDigest md5Tool = MessageDigest.getInstance("MD5"); | |||
| byte[] md5Data = md5Tool.digest((vp.getString("loginPassword")).getBytes("UTF-8")); | |||
| String sn = toHexString(md5Data); | |||
| param.put("password", sn.toLowerCase());//优惠券编号 | |||
| Map map = generateMap("3c.discount.verifyuser",param); | |||
| log.info("jieshunv2 verifyuser :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(VERIFY_USER, vp.getString("cid"), map, token,vp.getString("version"),vp.getString("signkey")); | |||
| } catch (NoSuchAlgorithmException e) { | |||
| log.error("jieshunv2 verifyuser error.park:"+wxPark.getId(),e); | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"jieshunv2 verifyuser error.park:"+wxPark.getId()+".error"+e.getMessage()); | |||
| } catch (UnsupportedEncodingException e) { | |||
| log.error("jieshunv2 verifyuser error.park:"+wxPark.getId(),e); | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"jieshunv2 verifyuser error.park:"+wxPark.getId()+".error"+e.getMessage()); | |||
| } | |||
| } | |||
| /** | |||
| * 查询门店打折方案 | |||
| */ | |||
| public String querySalePlan(WxPark wxPark,String token,String userId) { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("userId", userId);//商户编号 | |||
| Map map = generateMap("3c.discount.querysaleplan",param); | |||
| log.info("jieshunv2 querySalePlan :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(QUERY_PLAN, vp.getString("cid"), map, token,vp.getString("version"),vp.getString("signkey")); | |||
| } | |||
| /** | |||
| * 使用打折方案 | |||
| */ | |||
| public String executediscount(WxPark wxPark,String planId,String userId,String carNumber,String token) { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("planId", planId);//商户编号 | |||
| param.put("userId", userId);//优惠券编号 | |||
| param.put("carOrCardNo", handleCarNumber(carNumber));//优惠券编号 | |||
| Map map = generateMap("3c.discount.executediscount",param); | |||
| log.info("jieshunv2 executediscount :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(PLAN_EXECUTE, vp.getString("cid"), map, token,vp.getString("version"),vp.getString("signkey")); | |||
| } | |||
| /*token认证登陆**/ | |||
| private static String ProcLogin(String clientId,String clientSecret) { | |||
| String url = TOKEN_URL +"grant_type=client_credentials&scope=server&client_id="+clientId+"&client_secret="+clientSecret; | |||
| return Proc(url,content_type_token,null,null); | |||
| } | |||
| /** | |||
| * 优惠券使用完毕,0元停车费需调用次接口结清订单 | |||
| * @param wxPark | |||
| * @param planId | |||
| * @param userId | |||
| * @param carNumber | |||
| * @param token | |||
| * @return | |||
| */ | |||
| public String notifyOrderResult(WxPark wxPark,String orderNo,String token) { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("orderNo", orderNo);//商户编号 | |||
| param.put("tradeStatus", 0);//优惠券编号 | |||
| param.put("isCallBack", 0);//优惠券编号 | |||
| Map map = generateMap("3c.pay.notifyorderresult",param); | |||
| log.info("jieshunv2 notifyOrderResult :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(PLAN_EXECUTE, vp.getString("cid"), map, token,vp.getString("version"),vp.getString("signkey")); | |||
| } | |||
| private static String ProcBussiness(String url,String cid,Map<String,Object> param,String token) { | |||
| try { | |||
| MessageDigest md5Tool = MessageDigest.getInstance("MD5"); | |||
| String p = JSON.toJSONString(param); | |||
| byte[] md5Data = md5Tool.digest((p+signKey).getBytes("UTF-8")); | |||
| String sn = toHexString(md5Data); | |||
| if (url.contains("?")) { | |||
| url = url + "&"; | |||
| }else { | |||
| url = url + "?"; | |||
| } | |||
| url = url+"cid="+cid+"&tn="+token+"&sn="+sn+"&v="+version+"&p="+URLEncoder.encode(p, "UTF-8"); | |||
| // | |||
| return Proc(url,null); | |||
| } catch (NoSuchAlgorithmException e) { | |||
| log.error("jieshunv2 request error.",e); | |||
| } catch (UnsupportedEncodingException e) { | |||
| log.error("jieshunv2 request error.",e); | |||
| } | |||
| return null; | |||
| } | |||
| private static String toHexString(byte[] bytes) { | |||
| StringBuffer buffer = new StringBuffer(); | |||
| for (int i = 0; i < bytes.length; i++) { | |||
| buffer.append(String.format("%02X", bytes[i])); | |||
| } | |||
| return buffer.toString(); | |||
| } | |||
| private static String content_type_token = "application/x-www-form-urlencoded"; | |||
| private static String content_type_request = "application/json"; | |||
| private static String Proc(String url, String conentType,Map<String,Object> params,String token) { | |||
| CloseableHttpClient httpClient = HttpClients.createDefault(); | |||
| HttpPost httpPost = new HttpPost(url); | |||
| httpPost.addHeader(HTTP.CONTENT_TYPE,conentType); | |||
| httpPost.addHeader("Accept", "application/json"); | |||
| httpPost.addHeader("Accept-Encoding", "UTF-8"); | |||
| if (!StringUtils.isBlank(token)) { | |||
| httpPost.addHeader("Authorization-YR", "Bearer "+token); | |||
| httpPost.addHeader("Accept-Language", "zh-CN"); | |||
| } | |||
| if (null != params) { | |||
| try { | |||
| httpPost.setEntity(new StringEntity(JSONObject.toJSONString(params),ContentType.create("application/json","utf-8"))); | |||
| } catch (Exception e) { | |||
| log.error(e.getLocalizedMessage(),e); | |||
| return null; | |||
| } | |||
| } | |||
| public static String request(Map<String, Object> requestParams, String appId) { | |||
| String cipher = AesUtils.encryptCtrMode(JSONObject.toJSONString(requestParams), KEY, IV); | |||
| Map<String, Object> params = new HashMap<>(); | |||
| params.put("appId", appId); | |||
| params.put("cipher", cipher); | |||
| params.put("timestamp", System.currentTimeMillis()); | |||
| if (null != params) { | |||
| log.info("dahua httpRequest:[url]"+url+"[params]"+JSON.toJSONString(params)); | |||
| }else { | |||
| log.info("dahua httpRequest:[url]"+url); | |||
| } | |||
| HttpResponse response = null; | |||
| try { | |||
| //return HttpUtil.doPost(URL, JSONObject.toJSONString(params)); | |||
| return null; | |||
| response = httpClient.execute(httpPost); | |||
| } catch (Exception e) { | |||
| return null; | |||
| log.error(e.getLocalizedMessage(),e); | |||
| } | |||
| } | |||
| String result = null; | |||
| } | |||
| //打印StatusLine | |||
| log.debug("StatusLine: " + response.getStatusLine()); | |||
| try{ | |||
| //获取实体 | |||
| HttpEntity httpEntity= response.getEntity(); | |||
| result = EntityUtils.toString(httpEntity, "UTF-8"); | |||
| log.debug(result); | |||
| } catch (Exception e) { | |||
| log.error(e.getLocalizedMessage(),e); | |||
| } | |||
| try { //关闭流并释放资源 | |||
| httpClient.close(); | |||
| } catch (IOException e) { | |||
| log.error(e.getLocalizedMessage()); | |||
| } | |||
| return result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,190 @@ | |||
| package com.iformall.service.park.impl.dahua; | |||
| import java.text.ParseException; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONArray; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.common.IdWorker; | |||
| import com.iformall.domain.po.WxCarJSOrder; | |||
| import com.iformall.domain.po.WxPark; | |||
| import com.iformall.domain.vo.WxCarCYFVo; | |||
| import com.iformall.enums.EnumCarVendor; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.mapper.WxCarJSOrderMapper; | |||
| import com.iformall.service.WxParkService; | |||
| import com.iformall.service.park.ParkBatchCallBackAdapterService; | |||
| import com.iformall.service.park.ParkCallBackAdapterService; | |||
| import com.iformall.service.park.entity.ParkNotifyParam; | |||
| import com.iformall.service.park.impl.BaseParkService; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| @Slf4j | |||
| @Service | |||
| public class JieShunV2ParkCallbackService extends BaseParkService implements ParkBatchCallBackAdapterService { | |||
| @Autowired | |||
| DaHuaParkService jieshunParkService; | |||
| @Autowired | |||
| WxParkService wxParkService; | |||
| @Autowired | |||
| WxCarJSOrderMapper wxCarJSOrderMapper; | |||
| private String handleCarNumber(String carNumber) { | |||
| if (StringUtils.isBlank(carNumber)) { | |||
| return "空车牌"; | |||
| } | |||
| if (carNumber.contains("-")) { | |||
| carNumber = carNumber.replaceAll("-", ""); | |||
| } | |||
| return carNumber; | |||
| } | |||
| /** | |||
| * {dataItems=[{"inTime":"2020-12-09 11:21:15","carNumber":"浙-AF81797","inCarPhoto":"p201127315/NISSP_IMG_PARK_IN/20201209/a9f1130651b9493f8eab64f14afbdd47","isReal":0,"itemId":"a9f1130651b9493f8eab64f14afbdd47","inOperator":"超级管理员","equipName":"东门入口","parkName":"杭州东站西子国际","vehicleInfo":"{\"plateNo\":\"浙-AF81797\",\"plateColor\":\"GREEN\",\"plateBackColor\":0,\"plateWordColor\":0,\"vehicleColor\":null,\"vehicleLogo\":null,\"vehicleModel\":null,\"mainModel\":0,\"subModel\":0,\"vehicleModelTrust\":0,\"mainModelTrust\":0,\"subModelTrust\":0,\"plateNoTrust\":1,\"vehicleLogoTrust\":0,\"vehicleColorTrust\":0}","equipCode":"208202496","parkCode":"p201127315"}], pno=dzxzgj, sn=6C958D99D2769AA16F3A3F06E962263F, tn=-2, ts=20201209112118886, ve=1.0} | |||
| */ | |||
| @Override | |||
| public List<ParkNotifyParam> parseInNoticyParam(Object param) { | |||
| Map<String,Object> paramm = (Map<String, Object>) param; | |||
| String liststr = (String) paramm.get("dataItems"); | |||
| JSONArray list = JSONArray.parseArray(liststr); | |||
| if (null != list && list.size() > 0 ) { | |||
| List<ParkNotifyParam> retList = new ArrayList<ParkNotifyParam>(); | |||
| for (int i = 0 ; i < list.size() ; i ++) { | |||
| Map<String,Object> map = (Map<String, Object>) list.get(i); | |||
| ParkNotifyParam ret = parseInNoticyParamSingle(map); | |||
| if (null != ret ) { | |||
| retList.add(ret); | |||
| } | |||
| } | |||
| return retList; | |||
| } | |||
| return null; | |||
| } | |||
| private ParkNotifyParam parseInNoticyParamSingle(Map<String,Object> paramMap) { | |||
| String carNumber = paramMap.get("carNumber").toString(); | |||
| String parkCode = paramMap.get("parkCode").toString(); | |||
| String parkName = paramMap.get("parkName").toString(); | |||
| String synId = paramMap.get("itemId").toString(); | |||
| String entranceTime = paramMap.get("inTime").toString(); | |||
| ParkNotifyParam p = new ParkNotifyParam(); | |||
| String realCarNumber = handleCarNumber(carNumber); | |||
| p.setCarNumber(realCarNumber); | |||
| p.setParkId(parkCode); | |||
| p.setParkName(parkName); | |||
| p.setSynId(synId); | |||
| try { | |||
| p.setEntranceTime(DaHuaUtil.utcToLocal(entranceTime)); | |||
| } catch (ParseException e) { | |||
| log.error("jieshun entranceTime format error",e); | |||
| return null; | |||
| } | |||
| return p; | |||
| } | |||
| @Override | |||
| public List<ParkNotifyParam> parseOutNoticyParam(Object param) { | |||
| Map<String,Object> paramm = (Map<String, Object>) param; | |||
| String liststr = (String) paramm.get("dataItems"); | |||
| JSONArray list = JSONArray.parseArray(liststr); | |||
| if (null != list && list.size() > 0 ) { | |||
| List<ParkNotifyParam> retList = new ArrayList<ParkNotifyParam>(); | |||
| for (int i = 0 ; i < list.size() ; i ++) { | |||
| Map<String,Object> map = (Map<String, Object>) list.get(i); | |||
| ParkNotifyParam ret = parseOutNoticyParamSingle(map); | |||
| if (null != ret ) { | |||
| retList.add(ret); | |||
| } | |||
| } | |||
| return retList; | |||
| } | |||
| return null; | |||
| } | |||
| private ParkNotifyParam parseOutNoticyParamSingle(Map<String, Object> paramMap) { | |||
| String carNumber = paramMap.get("carNumber").toString(); | |||
| String parkCode = paramMap.get("parkCode").toString(); | |||
| String parkName = paramMap.get("parkName").toString(); | |||
| String synId = paramMap.get("itemId").toString(); | |||
| String entranceTime = paramMap.get("outTime").toString(); | |||
| String realCarNumber = handleCarNumber(carNumber); | |||
| ParkNotifyParam p = new ParkNotifyParam(); | |||
| p.setCarNumber(realCarNumber); | |||
| p.setParkId(parkCode); | |||
| p.setParkName(parkName); | |||
| p.setSynId(synId); | |||
| try { | |||
| p.setEntranceTime(DaHuaUtil.utcToLocal(entranceTime)); | |||
| } catch (ParseException e) { | |||
| log.error("cyf entranceTime format error",e); | |||
| return null; | |||
| } | |||
| try { | |||
| p.setOutTime(DaHuaUtil.utcToLocal(entranceTime)); | |||
| } catch (ParseException e) { | |||
| log.error("cyf outTime format error",e); | |||
| return null; | |||
| } | |||
| p.setFee(String.valueOf(paramMap.get("ssMoney"))); | |||
| return p; | |||
| } | |||
| @Override | |||
| public List<ParkNotifyParam> parseUnbindNoticyParam(Object param) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public List<ParkNotifyParam> parsePaidNoticyParam(Object param) { | |||
| Map<String,Object> paramm = (Map<String, Object>) param; | |||
| String liststr = (String) paramm.get("dataItems"); | |||
| JSONArray list = JSONArray.parseArray(liststr); | |||
| if (null != list && list.size() > 0 ) { | |||
| List<ParkNotifyParam> retList = new ArrayList<ParkNotifyParam>(); | |||
| for (int i = 0 ; i < list.size() ; i ++) { | |||
| Map<String,Object> map = (Map<String, Object>) list.get(i); | |||
| ParkNotifyParam ret = parsePaidNoticyParamSingle(map); | |||
| if (null != ret ) { | |||
| retList.add(ret); | |||
| } | |||
| } | |||
| return retList; | |||
| } | |||
| return null; | |||
| } | |||
| DaHuaUtil jieshun = new DaHuaUtil(); | |||
| private ParkNotifyParam parsePaidNoticyParamSingle(Map<String,Object> vo) { | |||
| ParkNotifyParam p = new ParkNotifyParam(); | |||
| p.setCarNumber(handleCarNumber((String) vo.get("carNumber"))); | |||
| p.setParkId(String.valueOf(vo.get("parkCode"))); | |||
| p.setParkOrderId((String) vo.get("itemId")); | |||
| p.setSynId((String) vo.get("itemId")); | |||
| p.setFee(vo.get("ssMoney").toString()); | |||
| try { | |||
| p.setPayTime(jieshun.utcToLocal((String)vo.get("feesTime"))); | |||
| } catch (ParseException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return p; | |||
| } | |||
| } | |||