Просмотр исходного кода

add ketuo car

release_toaliyun_real
lin 2 лет назад
Родитель
Сommit
a5b8f547e7
9 измененных файлов: 711 добавлений и 9 удалений
  1. +111
    -0
      mallinkCallback/src/main/java/com/iformall/controller/callback/car/ketuo/WxCarKeTuoCallBackController.java
  2. +6
    -1
      mallinkService/pom.xml
  3. +6
    -1
      mallinkService/src/main/java/com/iformall/enums/EnumCarCmd.java
  4. +8
    -7
      mallinkService/src/main/java/com/iformall/enums/EnumCarVendor.java
  5. +8
    -0
      mallinkService/src/main/java/com/iformall/service/park/ParkFactory.java
  6. +26
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/BaseParkService.java
  7. +134
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/ketuo/KeTuoParkCallbackService.java
  8. +200
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/ketuo/KeTuoParkService.java
  9. +212
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/ketuo/KeTuoUtil.java

+ 111
- 0
mallinkCallback/src/main/java/com/iformall/controller/callback/car/ketuo/WxCarKeTuoCallBackController.java Просмотреть файл

@@ -0,0 +1,111 @@
package com.iformall.controller.callback.car.ketuo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.iformall.common.Result;
import com.iformall.controller.base.BaseController;
import com.iformall.controller.callback.car.WxParkCallBackBaseController;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxCarCYFVo;
import com.iformall.enums.EnumCarCmd;
import com.iformall.enums.EnumCarVendor;
import com.iformall.enums.EnumCouponSendSendType;
import com.iformall.enums.EnumPayWay;
import com.iformall.service.*;
import com.iformall.service.park.impl.cyf.CYFUtil;
import com.iformall.service.park.impl.tjd.TJDUtil;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author: furunxin
* @Date: 2020/7/6 15:29
* @Description: 车易付回调接口
*/

@Slf4j
@RestController
@RequestMapping("/keTuoCarCallback")
public class WxCarKeTuoCallBackController extends WxParkCallBackBaseController {

@Autowired
WxParkService wxParkService;

@Autowired
WxCarCmdLogService wxCarCmdLogService;

@Autowired
WxCUserService wxCUserService;

@Autowired
WxCUserCarService wxCUserCarService;

@Autowired
WxCouponSendService wxCouponSendService;

@Autowired
WxCarPayRecordService wxCarPayRecordService;

@Autowired
WxCUserBasicInfoService wxCUserBasicInfoService;

/**
* @description 科拓 车辆入场通知
* {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}
*
*
*
* @Params [paramMap]
* @return com.iformall.common.Result
* @Author furunxin
* @Date 2020/7/8 上午8:27
**/
@PostMapping(value = "/PostCarInInfo")
public Result parkInCallback(@RequestBody Map<String, Object> paramMap) {
log.info("["+getIpAddr()+"] keTuoCarCallback parkIn: " + paramMap.toString());
//解析车易付参数
return super.parkInCallBack(EnumCarVendor.CAR_KETUO, EnumCarCmd.CAR_KETUO_CALLBACK_PARK_IN, paramMap);
}


/**
* @description 车易付 车辆离场通知
* @Params [param]
* @return java.util.Map
* @Author furunxin
* @Date 2020/7/12 上午9:00
**/
@PostMapping(value = "/PostCarOutInfo")
public Result parkOutCallback(@RequestBody Map<String, Object> paramMap) {
log.info("["+getIpAddr()+"] keTuoCarCallback parkOut: " + paramMap.toString());
return super.parkOutCallBack(EnumCarVendor.CAR_KETUO, EnumCarCmd.CAR_KETUO_CALLBACK_PARK_OUT, paramMap);
}
@PostMapping(value = "/unbind")
public Result unbindCallback(@RequestBody Map<String, Object> paramMap) {
log.info("["+getIpAddr()+"] keTuoCarCallback unbind: " + paramMap.toString());
//解析车易付参数
return super.unbindCarCallBack(EnumCarVendor.CAR_KETUO, EnumCarCmd.CAR_KETUO_CALLBACK_UNBIND, paramMap);
}
@PostMapping(value = "/PostPayFeeInfo")
public Result paidCallback(@RequestBody Map<String, Object> paramMap) {
log.info("["+getIpAddr()+"] keTuoCarCallback paid: " + paramMap.toString());
//解析车易付参数
return super.paidCallback(EnumCarVendor.CAR_KETUO, EnumCarCmd.CAR_KETUO_CALLBACK_PAID, paramMap);
}
}

+ 6
- 1
mallinkService/pom.xml Просмотреть файл

@@ -39,7 +39,12 @@
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.2.0</version>
</dependency>
</dependency>
<dependency>
<groupId>com.iformall</groupId>
<artifactId>mallinkAdmin</artifactId>
<version>1.0</version>
</dependency>
</dependencies>

</project>

+ 6
- 1
mallinkService/src/main/java/com/iformall/enums/EnumCarCmd.java Просмотреть файл

@@ -44,7 +44,12 @@ public enum EnumCarCmd {
CAR_LIFANG_CALLBACK_PARK_IN(636,"立方进场通知"),
CAR_LIFANG_CALLBACK_PARK_OUT(637,"立方出场通知"),
CAR_LIFANG_CALLBACK_UNBIND(638,"立方解绑车牌通知"),
CAR_LIFANG_CALLBACK_PAID(639,"立方支付通知")
CAR_LIFANG_CALLBACK_PAID(639,"立方支付通知"),
CAR_KETUO_CALLBACK_PARK_IN(640,"科拓进场通知"),
CAR_KETUO_CALLBACK_PARK_OUT(641,"科拓出场通知"),
CAR_KETUO_CALLBACK_UNBIND(642,"科拓解绑车牌通知"),
CAR_KETUO_CALLBACK_PAID(643,"科拓支付通知")
;

public static EnumCarCmd getEnum(Integer code) {


+ 8
- 7
mallinkService/src/main/java/com/iformall/enums/EnumCarVendor.java Просмотреть файл

@@ -8,16 +8,17 @@ public enum EnumCarVendor {
// 1-ETCP, 2-TJD停简单 3-Dahua大华, 4-ShangAn尚安, 5-BoLink泊链,6-车易付
CAR_NOTFOUND(0, "无",false),
CAR_ETCP(1, "ETCP",false),
CAR_TJD(2, "TJD",false),
CAR_DAHUA(3, "DAHUA",false),
CAR_SHANGAN(4, "ShangAn",false),
CAR_BOLINK(5, "BoLink",false),
CAE_CYF(6,"CYF",false),
CAR_JIESHUN(7,"JIESHUN",true),
CAR_TJD(2, "TJD",false),// 【接口不支持未接通,不能使用】
CAR_DAHUA(3, "DAHUA",false),// 【接口不支持未接通,不能使用】
CAR_SHANGAN(4, "ShangAn",false),// 【接口不支持未接通,不能使用】
CAR_BOLINK(5, "BoLink",false),// 【接口不支持未接通,不能使用】
CAE_CYF(6,"CYF",false),// 【接口不支持未接通,不能使用】
CAR_JIESHUN(7,"JIESHUN",true),//捷顺老版本,西子用
CAR_JIESHUN_V2(10,"JIESHUNV2",true),//捷顺通用版本
CAR_HAIKANGWEISHI(8,"HAIKANGWEISHI",true),
CAR_FUTE(9,"FUTE",false),//深圳市福特智能科技有限公司
CAR_LIFANG(10,"LIFANG",false)//立方停车
CAR_LIFANG(10,"LIFANG",false),//立方停车【接口不支持未接通,不能使用】
CAR_KETUO(11,"KETUO",false)//科拓停车
;

public static EnumCarVendor getEnum(Integer code) {


+ 8
- 0
mallinkService/src/main/java/com/iformall/service/park/ParkFactory.java Просмотреть файл

@@ -21,6 +21,8 @@ import com.iformall.service.park.impl.jieshun.JieShunParkCallbackService;
import com.iformall.service.park.impl.jieshun.JieShunParkService;
import com.iformall.service.park.impl.jieshunV2.JieShunV2ParkCallbackService;
import com.iformall.service.park.impl.jieshunV2.JieShunV2ParkService;
import com.iformall.service.park.impl.ketuo.KeTuoParkCallbackService;
import com.iformall.service.park.impl.ketuo.KeTuoParkService;
import com.iformall.service.park.impl.lifang.LiFangParkCallbackService;
import com.iformall.service.park.impl.lifang.LiFangParkService;
import com.iformall.service.park.impl.shangan.ShangAnParkService;
@@ -49,6 +51,8 @@ public class ParkFactory {
FuteParkService futeParkService;
@Autowired
LiFangParkService lifangParkService;
@Autowired
KeTuoParkService keTuoParkService;
@Autowired
CYFParkCallbackService cyfCallbackService;
@@ -62,6 +66,8 @@ public class ParkFactory {
FuteParkCallbackService futeParkCallbackService;
@Autowired
LiFangParkCallbackService lifangParkCallbackService;
@Autowired
KeTuoParkCallbackService keTuoParkCallbackService;
private Map<Integer,ParkAdapterService> parkServiceMap ;
@@ -85,6 +91,7 @@ public class ParkFactory {
parkServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI.getCode(), haikangWeishiService);
parkServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkService);
parkServiceMap.put(EnumCarVendor.CAR_LIFANG.getCode(), lifangParkService);
parkServiceMap.put(EnumCarVendor.CAR_KETUO.getCode(), keTuoParkService);
return parkServiceMap;
}
@@ -108,6 +115,7 @@ public class ParkFactory {
callBackServiceMap.put(EnumCarVendor.CAE_CYF.getCode(), cyfCallbackService);
callBackServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkCallbackService);
callBackServiceMap.put(EnumCarVendor.CAR_LIFANG.getCode(), lifangParkCallbackService);
callBackServiceMap.put(EnumCarVendor.CAR_KETUO.getCode(), keTuoParkCallbackService);
return callBackServiceMap;
}


+ 26
- 0
mallinkService/src/main/java/com/iformall/service/park/impl/BaseParkService.java Просмотреть файл

@@ -6,9 +6,12 @@ import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxCUserBasicInfo;
import com.iformall.domain.po.WxCoupon;
import com.iformall.domain.po.WxPark;
import com.iformall.exception.MallinkException;
import com.iformall.service.park.impl.util.ParkHelper;

@Service
@@ -17,4 +20,27 @@ public class BaseParkService {
@Autowired
ParkHelper parkHelper;
protected boolean isReduceMoney(WxCoupon coupon) throws Exception{
//抵扣时长
if (coupon.getUnit().intValue() == 1 ) {
return false;
}else if (coupon.getUnit().intValue() == 0 ) {
return true;
}else {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"coupon has no config [unit]");
}
}
protected Integer getReduceValue(WxCoupon coupon) throws Exception{
//时长,小时
if (coupon.getUnit().intValue() == 1 ) {
return coupon.getPrice()/100;
}else if (coupon.getUnit().intValue() == 0 ) {
//分
return coupon.getPrice();
}else {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"coupon has no config [unit]");
}
}
}

+ 134
- 0
mallinkService/src/main/java/com/iformall/service/park/impl/ketuo/KeTuoParkCallbackService.java Просмотреть файл

@@ -0,0 +1,134 @@
package com.iformall.service.park.impl.ketuo;

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 KeTuoParkCallbackService extends BaseParkService implements ParkCallBackAdapterService {
@Autowired
KeTuoParkService keTuoParkService;
@Autowired
WxParkService wxParkService;
@Autowired
WxCarJSOrderMapper wxCarJSOrderMapper;
KeTuoUtil ketuo = new KeTuoUtil();
/**
* {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 ParkNotifyParam parseInNoticyParam(Object param) {
Map<String,Object> paramm = (Map<String, Object>) param;
String carNumber = paramm.get("plateNo").toString();
String parkCode = paramm.get("parkId").toString();
String synId = paramm.get("trafficId").toString();
String entranceTime = paramm.get("entryTime").toString();
ParkNotifyParam p = new ParkNotifyParam();
p.setCarNumber(carNumber);
p.setParkId(parkCode);
p.setParkName("ketuo");
p.setSynId(synId);
try {
p.setEntranceTime(ketuo.utcToLocal(entranceTime));
} catch (ParseException e) {
log.error("jieshun entranceTime format error",e);
return null;
}
return p;
}
@Override
public ParkNotifyParam parseOutNoticyParam(Object param) {
Map<String,Object> paramm = (Map<String, Object>) param;
String carNumber = paramm.get("plateNo").toString();
String parkCode = paramm.get("parkId").toString();
String synId = paramm.get("trafficId").toString();
String entranceTime = paramm.get("entryTime").toString();
String outTime = paramm.get("leaveTime").toString();
ParkNotifyParam p = new ParkNotifyParam();
p.setCarNumber(carNumber);
p.setParkId(parkCode);
p.setParkName("ketuo");
p.setSynId(synId);
try {
p.setEntranceTime(ketuo.utcToLocal(entranceTime));
} catch (ParseException e) {
log.error("cyf entranceTime format error",e);
return null;
}
try {
p.setOutTime(ketuo.utcToLocal(outTime));
} catch (ParseException e) {
log.error("cyf outTime format error",e);
return null;
}
Object payMentInfo = paramm.get("payMentInfo");
String fee = "0";
if (null != payMentInfo) {
JSONObject pay = JSON.parseObject(JSON.toJSONString(payMentInfo));
if (null != pay) {
fee = String.valueOf(pay.getInteger("paidMoney"));
}
}
p.setFee(fee);
return p;
}

@Override
public ParkNotifyParam parseUnbindNoticyParam(Object param) {
return null;
}

@Override
public ParkNotifyParam parsePaidNoticyParam(Object param) {
Map<String,Object> paramm = (Map<String, Object>) param;
ParkNotifyParam p = new ParkNotifyParam();
p.setCarNumber((String) paramm.get("plateNo"));
p.setParkId(String.valueOf(paramm.get("parkId")));
p.setParkOrderId((String) paramm.get("billId"));
p.setSynId((String) paramm.get("reqId"));
p.setFee(paramm.get("paidMoney").toString());
try {
p.setPayTime(ketuo.utcToLocal((String)paramm.get("payTime")));
} catch (ParseException e) {
e.printStackTrace();
}
return p;
}
}

+ 200
- 0
mallinkService/src/main/java/com/iformall/service/park/impl/ketuo/KeTuoParkService.java Просмотреть файл

@@ -0,0 +1,200 @@
package com.iformall.service.park.impl.ketuo;

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;

/**
*
*/
@Service
public class KeTuoParkService 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;
KeTuoUtil ketuo = new KeTuoUtil();
/**
* 先去捷顺注册,调用登陆获取令牌,然后根据令牌调用别的接口
* 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 {
return null;
}
@Override
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) throws Exception{
return "ketuo";
}

@Override
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) throws Exception{
return ketuoCarStopFee(paramMap, park,carNumber);
}
private ParkStopFee ketuoCarStopFee(Map<String, String> paramMap, WxPark park,String carNumber) throws Exception{
String ret = ketuo.getCarStopFee(park, carNumber);
if (StringUtils.isBlank(ret)) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "ketuo getCarStopFee error. has no result");
}
JSONObject retObj = JSON.parseObject(ret);
if (retObj.getIntValue("resCode") == 0){
JSONObject retObject = retObj.getJSONObject("data");
if (null == retObject ) {
throw new MallinkException(retObj.getInteger("resCode"), "ketuo getCarStopFee error. no order result"+carNumber);
}
Double totalFee = retObject.getDouble("payable");
String appId = "wx54e676273869baa6";
String parkOrderId = retObject.getString("orderNo");
Integer freeMinute = (Integer)park.getVendorParamsByKey("freeMinute");
String createTime = retObject.getString("entryTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss”
String endTime = retObject.getString("payTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss”
String payPath = "pages/index/index?lotId="+Integer.parseInt(park.getParkingId())+"&lpn="+carNumber;
return new ParkStopFee(parkOrderId,ketuo.utcToLocal(createTime),ketuo.utcToLocal(endTime),
String.valueOf(totalFee),appId,payPath,null,null,"请支付后"+freeMinute+"分钟内离场");
}else {
logger.error("ketuoCarStopFee error. paramMap: {} . ketuoResult: {}",JSON.toJSONString(paramMap),ret);
String msg = retObj.getString("resMsg");
throw new MallinkException(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "停车费获取失败:"+msg);
}
}

/**
* 使用3.8打折方案,3.9有限制如果领券了之后未使用,不能再次领券。导致出现异常之后,用户永远无法使用优惠券。
* @return
*/
@Override
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(),"当前停车券没有关联停车场优惠券配置[couponNo]。"+coupon.getTitle());
}
//查询停车费
ParkStopFee fee = ketuoCarStopFee(paramMap, park, carNumber);
//保存抵扣
boolean isReduceMoney = this.isReduceMoney(coupon);
Integer reduceValue = this.getReduceValue(coupon);
String executeRet = ketuo.executediscount(park, fee.getOrderId(), planNo, Integer.parseInt(fee.getRemainingFee()),isReduceMoney, reduceValue);
logger.info("ketuo executediscount result:"+executeRet);
JSONObject executeRetObj = JSON.parseObject(executeRet);
if (executeRetObj.getIntValue("resCode") == 0){
return new ResultData();
}else {
return new ResultData(executeRetObj.getIntValue("resCode"),"保存科拓支付信息失败。"+executeRetObj.getString("resMsg"));
}
}
@Override
public ParkCreatePayOrder createPayOrder(Map<String, String> paramMap, WxPark park, String carNumber) throws Exception {
return null;
}

@Override
public ParkPaidNotifyResult notifyPaid(WxPark park,ParkNotifyPaid notifyPaid) throws Exception {
return null;
}

@Override
public ResultData getParkStatus(WxPark park) throws Exception{
return new ResultData();
}

@Override
public boolean ignoreUseCouponCache() {
return false;
}

}

+ 212
- 0
mallinkService/src/main/java/com/iformall/service/park/impl/ketuo/KeTuoUtil.java Просмотреть файл

@@ -0,0 +1,212 @@
package com.iformall.service.park.impl.ketuo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.iformall.domain.po.WxPark;
import com.iformall.utils.Utility;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
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.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
* @author: furunxin
* @Date: 2020/7/1 17:16
* @Description: 车易付接口对接参数类
*/

@Slf4j
public class KeTuoUtil {

public static final String QUERY_FEE = "/api/wec/GetParkingPaymentInfo";
public static final String PAY_FEE = "/api/wec/PayParkingFee";

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 String getCarStopFee(WxPark wxPark,String carNumber){
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
JSONObject param = new JSONObject();
param.put("plateNo", carNumber);//车牌号
log.info("ketuo getCarStopFee :" + JSON.toJSONString(param));
return Proc(QUERY_FEE,"getParkingPaymentInfo", vp.getString("appId"), vp.getString("appSercet"), Integer.parseInt(wxPark.getParkingId()),vp.getString("version"),param);
}
/**
* 抵扣
*/
public String executediscount(WxPark wxPark,String orderNo,String couponNo,int fee, boolean isDiscountMoney,int discountValue) {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
JSONObject param = new JSONObject();
param.put("orderNo", orderNo);//车场订单号
param.put("payableAmount", fee);//应付金额
param.put("amount", 0);//支付金额(不包含减免部分),单位为分
param.put("payType", 4);//收费终端
param.put("payMethod", 1010);//付款方式
if (isDiscountMoney) {
param.put("freeMoney", discountValue);//减免总金额(单位 分)
}else {
param.put("freeTime", discountValue*3600);//减免总时长(单位 秒)
}
param.put("isCarLeave", 0);//车辆是否离场
Map freeDeail = new HashMap();
if (isDiscountMoney) {
freeDeail.put("money", discountValue);
freeDeail.put("time", 0);
}else {
freeDeail.put("money", 0);
freeDeail.put("time", discountValue*3600);
}
freeDeail.put("code", couponNo);//车场券编码
freeDeail.put("type", 1);
freeDeail.put("freeName", "fmMiniApp");
List<Map> freeDetails = new ArrayList<Map>();
freeDetails.add(freeDeail);
param.put("freeDetail", JSON.toJSONString(freeDetails));//json数组字符串
log.info("ketuo executediscount :" + JSON.toJSONString(param));
return Proc(PAY_FEE,"payParkingFee", vp.getString("appId"), vp.getString("appSercet"), Integer.parseInt(wxPark.getParkingId()),vp.getString("version"),param);
}
private static String Proc(String url, String serviceCode,String appId,String appSercet,Integer parkId,String version, JSONObject params) {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader(HTTP.CONTENT_TYPE,"application/json");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Accept-Encoding", "UTF-8");
httpPost.addHeader("version",version);//1.0.0

if (null != params) {
try {
params.put("appId", appId);
params.put("parkId", parkId);
params.put("serviceCode", serviceCode);
params.put("ts", String.valueOf(Calendar.getInstance().getTimeInMillis()));
params.put("key", paramsSign(params, appSercet));
params.put("reqId", Utility.generate32UUID()+String.valueOf(Calendar.getInstance().getTimeInMillis()));
httpPost.setEntity(new StringEntity(JSONObject.toJSONString(params),ContentType.create("application/json","utf-8")));
} catch (Exception e) {
log.error(e.getLocalizedMessage(),e);
return null;
}
}

if (null != params) {
log.info("ketuo httpRequest:[url]"+url+"[params]"+JSON.toJSONString(params));
}else {
log.info("ketuo httpRequest:[url]"+url);
}
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (Exception e) {
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;
}
private static String paramsSign(JSONObject requestBody, String appSecret) {
TreeMap<String, String> params = new TreeMap<>();
//过滤掉key,appId字段,空属性及Map或List等复杂对象
requestBody.entrySet().stream().filter(
p -> !"key".equals(p.getKey())
&& !"appId".equals(p.getKey())
&& p.getValue() != null
&& !(p.getValue() instanceof Map)
&& !(p.getValue() instanceof Iterable))
.forEach(p -> {
if (!p.getValue().equals("")) {
params.put(p.getKey(), p.getValue().toString());
}
});
//拼接appSecret
String temp = Joiner.on("&").withKeyValueSeparator("=").join(params).concat("&").concat(appSecret);
return md5(temp).toUpperCase();
}

/**
* 对文本执行 md5 摘要加密, 此算法与 mysql,JavaScript生成的md5摘要进行过一致性对比.
*
* @param plainText
* @return 返回值中的字母为小写
*/
private static String md5(String plainText) {
if (null == plainText) {
plainText = "";
}
String mD5Str = null;
try {
// JDK 支持以下6种消息摘要算法,不区分大小写
// md5,sha(sha-1),md2,sha-256,sha-384,sha-512
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes(StandardCharsets.UTF_8));
byte[] b = md.digest();
int i;
StringBuilder builder = new StringBuilder(32);
for (byte value : b) {
i = value;
if (i < 0) {
i += 256;
}
if (i < 16) {
builder.append("0");
}
builder.append(Integer.toHexString(i));
}
mD5Str = builder.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return mD5Str;
}
}

Загрузка…
Отмена
Сохранить