| @@ -12,6 +12,7 @@ public enum EnumCarVendor { | |||||
| CAR_JIESHUN(7,"JIESHUN",true),//捷顺老版本,西子用 | CAR_JIESHUN(7,"JIESHUN",true),//捷顺老版本,西子用 | ||||
| CAR_JIESHUN_V2(10,"JIESHUNV2",true),//捷顺通用版本 | CAR_JIESHUN_V2(10,"JIESHUNV2",true),//捷顺通用版本 | ||||
| CAR_HAIKANGWEISHI(8,"HAIKANGWEISHI",true), | CAR_HAIKANGWEISHI(8,"HAIKANGWEISHI",true), | ||||
| CAR_HAIKANGWEISHI_V2(18,"HAIKANGWEISHIV2",true), | |||||
| CAR_FUTE(9,"FUTE",false),//深圳市福特智能科技有限公司 | CAR_FUTE(9,"FUTE",false),//深圳市福特智能科技有限公司 | ||||
| CAR_KETUO(11,"KETUO",false),//科拓停车 | CAR_KETUO(11,"KETUO",false),//科拓停车 | ||||
| CAR_LIFANG(12,"LIFANG",false),// 立方【接口不支持未接通,不能使用】 | CAR_LIFANG(12,"LIFANG",false),// 立方【接口不支持未接通,不能使用】 | ||||
| @@ -12,6 +12,8 @@ import com.iformall.service.park.impl.fute.FuteParkCallbackService; | |||||
| import com.iformall.service.park.impl.fute.FuteParkService; | import com.iformall.service.park.impl.fute.FuteParkService; | ||||
| import com.iformall.service.park.impl.haikangweishi.HaiKangWeiShiParkCallbackService; | import com.iformall.service.park.impl.haikangweishi.HaiKangWeiShiParkCallbackService; | ||||
| import com.iformall.service.park.impl.haikangweishi.HaiKangWeiShiParkService; | import com.iformall.service.park.impl.haikangweishi.HaiKangWeiShiParkService; | ||||
| import com.iformall.service.park.impl.haikangweishiv2.HaiKangWeiShiV2ParkCallbackService; | |||||
| import com.iformall.service.park.impl.haikangweishiv2.HaiKangWeiShiV2ParkService; | |||||
| import com.iformall.service.park.impl.jieshun.JieShunParkCallbackService; | import com.iformall.service.park.impl.jieshun.JieShunParkCallbackService; | ||||
| import com.iformall.service.park.impl.jieshun.JieShunParkService; | import com.iformall.service.park.impl.jieshun.JieShunParkService; | ||||
| import com.iformall.service.park.impl.jieshunV2.JieShunV2ParkCallbackService; | import com.iformall.service.park.impl.jieshunV2.JieShunV2ParkCallbackService; | ||||
| @@ -48,6 +50,8 @@ public class ParkFactory { | |||||
| @Autowired | @Autowired | ||||
| HaiKangWeiShiParkService haikangWeishiService; | HaiKangWeiShiParkService haikangWeishiService; | ||||
| @Autowired | @Autowired | ||||
| HaiKangWeiShiV2ParkService haikangWeishiV2Service; | |||||
| @Autowired | |||||
| FuteParkService futeParkService; | FuteParkService futeParkService; | ||||
| @Autowired | @Autowired | ||||
| LiFangParkService lifangParkService; | LiFangParkService lifangParkService; | ||||
| @@ -65,6 +69,8 @@ public class ParkFactory { | |||||
| @Autowired | @Autowired | ||||
| HaiKangWeiShiParkCallbackService haikangWeishiCallBackService; | HaiKangWeiShiParkCallbackService haikangWeishiCallBackService; | ||||
| @Autowired | @Autowired | ||||
| HaiKangWeiShiV2ParkCallbackService haikangWeishiV2CallBackService; | |||||
| @Autowired | |||||
| FuteParkCallbackService futeParkCallbackService; | FuteParkCallbackService futeParkCallbackService; | ||||
| @Autowired | @Autowired | ||||
| LiFangParkCallbackService lifangParkCallbackService; | LiFangParkCallbackService lifangParkCallbackService; | ||||
| @@ -91,6 +97,7 @@ public class ParkFactory { | |||||
| parkServiceMap.put(EnumCarVendor.CAR_JIESHUN.getCode(), jieshunService); | parkServiceMap.put(EnumCarVendor.CAR_JIESHUN.getCode(), jieshunService); | ||||
| parkServiceMap.put(EnumCarVendor.CAR_JIESHUN_V2.getCode(), jieshunV2Service); | parkServiceMap.put(EnumCarVendor.CAR_JIESHUN_V2.getCode(), jieshunV2Service); | ||||
| parkServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI.getCode(), haikangWeishiService); | parkServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI.getCode(), haikangWeishiService); | ||||
| parkServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI_V2.getCode(), haikangWeishiV2Service); | |||||
| parkServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkService); | parkServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkService); | ||||
| parkServiceMap.put(EnumCarVendor.CAR_LIFANG.getCode(), lifangParkService); | parkServiceMap.put(EnumCarVendor.CAR_LIFANG.getCode(), lifangParkService); | ||||
| parkServiceMap.put(EnumCarVendor.CAR_KETUO.getCode(), keTuoParkService); | parkServiceMap.put(EnumCarVendor.CAR_KETUO.getCode(), keTuoParkService); | ||||
| @@ -116,6 +123,7 @@ public class ParkFactory { | |||||
| callBackServiceMap = new ConcurrentHashMap<Integer, ParkCallBackAdapterService>(); | callBackServiceMap = new ConcurrentHashMap<Integer, ParkCallBackAdapterService>(); | ||||
| callBackServiceMap.put(EnumCarVendor.CAE_CYF.getCode(), cyfCallbackService); | callBackServiceMap.put(EnumCarVendor.CAE_CYF.getCode(), cyfCallbackService); | ||||
| callBackServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkCallbackService); | callBackServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkCallbackService); | ||||
| callBackServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI_V2.getCode(), haikangWeishiV2CallBackService); | |||||
| callBackServiceMap.put(EnumCarVendor.CAR_LIFANG.getCode(), lifangParkCallbackService); | callBackServiceMap.put(EnumCarVendor.CAR_LIFANG.getCode(), lifangParkCallbackService); | ||||
| callBackServiceMap.put(EnumCarVendor.CAR_KETUO.getCode(), keTuoParkCallbackService); | callBackServiceMap.put(EnumCarVendor.CAR_KETUO.getCode(), keTuoParkCallbackService); | ||||
| callBackServiceMap.put(EnumCarVendor.CAR_DAHUA.getCode(), dahuaCallbackService); | callBackServiceMap.put(EnumCarVendor.CAR_DAHUA.getCode(), dahuaCallbackService); | ||||
| @@ -153,6 +153,7 @@ public class HaiKangWeiShiParkService extends BaseParkService implements ParkAda | |||||
| String _createTime = attribute.getString("entranceTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss” | String _createTime = attribute.getString("entranceTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss” | ||||
| String _endTime = attribute.getString("costTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss” | String _endTime = attribute.getString("costTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss” | ||||
| String payPath = ""; | String payPath = ""; | ||||
| Integer freeMinute = (Integer)park.getVendorParamsByKey("freeMinute"); | |||||
| return new ParkStopFee(parkOrderId,haikang.utcToLocal(_createTime),haikang.utcToLocal(_endTime), | return new ParkStopFee(parkOrderId,haikang.utcToLocal(_createTime),haikang.utcToLocal(_endTime), | ||||
| String.valueOf(attribute.getDouble("shouldCost")),appId,payPath,null,null,"0元请勿使用优惠券,无法退回。支付后15分钟内离场"); | String.valueOf(attribute.getDouble("shouldCost")),appId,payPath,null,null,"0元请勿使用优惠券,无法退回。支付后15分钟内离场"); | ||||
| } | } | ||||
| @@ -0,0 +1,104 @@ | |||||
| package com.iformall.service.park.impl.haikangweishiv2; | |||||
| import com.iformall.service.WxParkService; | |||||
| 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; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| @Slf4j | |||||
| @Service | |||||
| public class HaiKangWeiShiV2ParkCallbackService extends BaseParkService implements ParkCallBackAdapterService { | |||||
| @Autowired | |||||
| WxParkService wxParkService; | |||||
| /** | |||||
| * {card_number=, user_name=, park_id=1101780001, sign=001b2dbfa21089a14274c4d3e330cd82, in_channel_id=营销中心入口, | |||||
| * remark=正常入场, in_channel=2f48a7a9-1be5-406c-b078-51d3506adab2, park_flag=1, area_id=90221771-fe94-4cfd-80d7-c14e7c97e775, | |||||
| * empty_plot=3490, user_no=, car_type=36, uid=001, in_time=1676563040, car_number=湘A87M0K, c_type=通道扫牌, in_optname=监控室, | |||||
| * order_id=46eea0c8-8a0b-4583-9273-f9843a42ddec, in_image=} | |||||
| */ | |||||
| @Override | |||||
| public ParkNotifyParam parseInNoticyParam(Object param) { | |||||
| Map<String,Object> paramMap = (Map<String, Object>) param; | |||||
| String carNumber = paramMap.get("car_number").toString(); | |||||
| String parkCode = paramMap.get("park_id").toString(); | |||||
| String parkName = ""; | |||||
| String synId = paramMap.get("order_id").toString(); | |||||
| Integer inTime = (Integer)paramMap.get("in_time"); | |||||
| ParkNotifyParam p = new ParkNotifyParam(); | |||||
| p.setCarNumber(carNumber); | |||||
| p.setParkId(parkCode); | |||||
| p.setParkName(parkName); | |||||
| p.setSynId(synId); | |||||
| try { | |||||
| p.setEntranceTime(new Date(inTime.longValue()*1000)); | |||||
| } catch (Exception e) { | |||||
| log.error("fute entranceTime format error",e); | |||||
| return null; | |||||
| } | |||||
| return p; | |||||
| } | |||||
| /** | |||||
| * {out_channel=08497aa1-bc39-4223-9659-83fba2680082, sign=37316011fd7f4997f0937ae839246968, remark=正常出场, | |||||
| * in_channel=cdb95bb9-b43e-4a4c-83cc-99d0e5e1f7d4, empty_plot=19, car_type=36, duration=99, uid=001, total=0.0000, | |||||
| * freereasons=, out_image=, out_optname=监控室, pay_type=cash, in_optcode=001, reduce_amount=0.0000, out_time=1676562822, | |||||
| * card_number=, park_id=1101780001, in_channel_id=南门入口相机, auth_code=, in_time=1676556899, ouid=001, out_type=通道扫牌, | |||||
| * car_number=湘A67H9R, out_order_id=03d6973e-0276-4264-bd0a-5aee59e6cf98, c_type=通道扫牌, pay_channel=0, | |||||
| * amount_receivable=0.0000, in_optname=监控室, out_channel_id=南门出口直行相机, order_id=03d6973e-0276-4264-bd0a-5aee59e6cf98} | |||||
| */ | |||||
| @Override | |||||
| public ParkNotifyParam parseOutNoticyParam(Object param) { | |||||
| Map<String,Object> paramMap = (Map<String, Object>) param; | |||||
| String carNumber = paramMap.get("car_number").toString(); | |||||
| String parkCode = paramMap.get("park_id").toString(); | |||||
| String parkName = ""; | |||||
| String synId = paramMap.get("order_id").toString(); | |||||
| Integer inTime = (Integer)paramMap.get("in_time"); | |||||
| Integer outTime = (Integer)paramMap.get("out_time"); | |||||
| ParkNotifyParam p = new ParkNotifyParam(); | |||||
| p.setCarNumber(carNumber); | |||||
| p.setParkId(parkCode); | |||||
| p.setParkName(parkName); | |||||
| p.setSynId(synId); | |||||
| try { | |||||
| p.setEntranceTime(new Date(inTime.longValue()*1000)); | |||||
| } catch (Exception e) { | |||||
| log.error("fute entranceTime format error",e); | |||||
| return null; | |||||
| } | |||||
| try { | |||||
| p.setOutTime(new Date(outTime.longValue()*1000)); | |||||
| } catch (Exception e) { | |||||
| log.error("fute outTime format error",e); | |||||
| return null; | |||||
| } | |||||
| p.setFee(String.valueOf(paramMap.get("amount_receivable"))); | |||||
| return p; | |||||
| } | |||||
| @Override | |||||
| public ParkNotifyParam parseUnbindNoticyParam(Object param) { | |||||
| return null; | |||||
| } | |||||
| @Override | |||||
| public ParkNotifyParam parsePaidNoticyParam(Object param) { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,214 @@ | |||||
| package com.iformall.service.park.impl.haikangweishiv2; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONArray; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| 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.domain.vo.WxCouponOrderCarCVo; | |||||
| import com.iformall.domain.vo.WxParkCouponConfig; | |||||
| import com.iformall.exception.MallinkException; | |||||
| 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.utils.DateUtils; | |||||
| import com.iformall.utils.RedisCacheUtils; | |||||
| import com.iformall.utils.RedisLock; | |||||
| 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 java.math.BigDecimal; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 福特停车 | |||||
| * http://hsh.appykt.com/ | |||||
| * 1287230005_888888 123456 | |||||
| */ | |||||
| @Service | |||||
| public class HaiKangWeiShiV2ParkService 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; | |||||
| HaiKangWeiShiV2Util haikangV2 = new HaiKangWeiShiV2Util(); | |||||
| private String getCacheToken(WxPark park) { | |||||
| String token = RedisCacheUtils.getCacheString(redisTemplate, "carStop:haikangv2token:"+park.getId()); | |||||
| if (StringUtils.isBlank(token)) { | |||||
| String lockKey = "carStop:haikangv2tokenlock:"+park.getTenantId(); | |||||
| long time = System.currentTimeMillis() + 2000; | |||||
| String timeStr = String.valueOf(time); | |||||
| if (redisLock.lock2(lockKey, timeStr)) { | |||||
| token = haikangV2.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:haikangv2token:"+park.getId()); | |||||
| } | |||||
| private void setCacheToken(WxPark park,String token) { | |||||
| RedisCacheUtils.cache(redisTemplate, "carStop:haikangv2token:"+park.getId(), token, 36000); | |||||
| } | |||||
| @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 "haikangV2"; | |||||
| } | |||||
| @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 haiKangWeiShiCarStopFee(paramMap, park,carNumber); | |||||
| } | |||||
| private ParkStopFee haiKangWeiShiCarStopFee(Map<String, String> paramMap, WxPark park,String carNumber) throws Exception{ | |||||
| //如果车牌号是鄂AAAAAA, 为测试车牌 | |||||
| if (carNumber.equals("鄂AAAAAA")) { | |||||
| return new ParkStopFee("-111",haikangV2.utcToLocal("2020-12-16 00:00:00"),haikangV2.utcToLocal("2020-12-17 00:00:00"), | |||||
| "0.01","","payPath",null,"测试车牌,仅测试用",null); | |||||
| }else if(carNumber.equals("鄂AAAAAB")) { | |||||
| throw new MallinkException(21000,"车辆未入场"); | |||||
| } | |||||
| JSONObject attribute = haikangV2.getCarStopFee(park, carNumber, getCacheToken(park)); | |||||
| String appId = ""; | |||||
| String parkOrderId = attribute.getString("billCode"); | |||||
| Date _createTime = (Date) attribute.get("enterTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss” | |||||
| Date _endTime = DateUtils.getSecondsTimeAfter(attribute.getIntValue("parkPeriodTime"), _createTime);//离场时间,格式为“yyyy-MM-dd HH:mi:ss” | |||||
| String payPath = ""; | |||||
| Integer freeMinute = (Integer)park.getVendorParamsByKey("freeMinute"); | |||||
| return new ParkStopFee(parkOrderId,_createTime,_endTime, | |||||
| String.valueOf(attribute.getDouble("payMoney")/100),appId,payPath,null,null,"0元请勿使用优惠券,无法退回。支付后"+freeMinute+"分钟内离场"); | |||||
| } | |||||
| /** | |||||
| * @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 reduceType = valueMap.get("reduceType"); | |||||
| if (StringUtils.isBlank(reduceType)) { | |||||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券未设置停车场优惠券配置参数[减免类型]。"+coupon.getTitle()); | |||||
| } | |||||
| if ((!"1".equals(reduceType)) && (!"2".equals(reduceType))) { | |||||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券设置停车场优惠券配置参数[减免类型]值非法。"+coupon.getTitle()); | |||||
| } | |||||
| String reduceValueStr = valueMap.get("reduceValue"); | |||||
| if (StringUtils.isBlank(reduceValueStr)) { | |||||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券未设置停车场优惠券配置参数[减免数值]。"+coupon.getTitle()); | |||||
| } | |||||
| Integer reduceValue = 0; | |||||
| try { | |||||
| reduceValue = Integer.parseInt(reduceValueStr); | |||||
| }catch(Exception e) { | |||||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券设置停车场优惠券配置参数[减免数值]值非法。"+coupon.getTitle()); | |||||
| } | |||||
| boolean isTimeCash = false; | |||||
| if ("1".equals(reduceType)) { | |||||
| isTimeCash = true; | |||||
| } | |||||
| //查询临停信息,判断缓存是否已经存在 | |||||
| JSONObject stopInfo = haikangV2.getCarStopFee(park, getCacheToken(park), carNumber); | |||||
| String inRecordSyscode = stopInfo.getString("billCode"); | |||||
| Integer used = RedisCacheUtils.getCacheInteger(redisTemplate, "carStop:haikangv2StopInfoUseCoupon:"+carNumber+":"+inRecordSyscode); | |||||
| if (null == used || (null != used && used.intValue() < 1) ) { | |||||
| //do nothing | |||||
| }else { | |||||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "已经使用过优惠券, 不能重复使用."); | |||||
| } | |||||
| JSONObject retObj = haikangV2.useCoupon(park,getCacheToken(park),carNumber,isTimeCash,reduceValue,coupon.getValidStartDate(),coupon.getValidEndDate()); | |||||
| RedisCacheUtils.cache(redisTemplate, "carStop:haikangv2StopInfoUseCoupon:"+carNumber+":"+inRecordSyscode, 1, 24*3600); | |||||
| return new ResultData(); | |||||
| } | |||||
| @Override | |||||
| public ParkCreatePayOrder createPayOrder(Map<String, String> paramMap, WxPark park, String carNumber) throws Exception { | |||||
| JSONObject result = haikangV2.getCarStopFee(park, getCacheToken(park), carNumber); | |||||
| Double price = result.getDouble("payMoney"); | |||||
| Integer fee = new BigDecimal(price).intValue(); | |||||
| return new ParkCreatePayOrder(result.getString("billCode"), fee); | |||||
| } | |||||
| @Override | |||||
| public ParkPaidNotifyResult notifyPaid(WxPark park,ParkNotifyPaid notifyPaid) throws Exception { | |||||
| JSONObject result = haikangV2.notifyPaid(park, notifyPaid.getParkOrderNo(), notifyPaid.getFee(),getCacheToken(park)); | |||||
| return new ParkPaidNotifyResult(true, result, null); | |||||
| } | |||||
| @Override | |||||
| public ResultData getParkStatus(WxPark park) throws Exception{ | |||||
| return new ResultData(); | |||||
| } | |||||
| @Override | |||||
| public boolean ignoreUseCouponCache() { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,301 @@ | |||||
| package com.iformall.service.park.impl.haikangweishiv2; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.WxPark; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.utils.DateUtils; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.apache.http.HttpEntity; | |||||
| import org.apache.http.HttpResponse; | |||||
| import org.apache.http.NameValuePair; | |||||
| import org.apache.http.client.methods.HttpPost; | |||||
| import org.apache.http.entity.ContentType; | |||||
| import org.apache.http.entity.StringEntity; | |||||
| import org.apache.http.entity.mime.MultipartEntityBuilder; | |||||
| import org.apache.http.entity.mime.content.StringBody; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import org.apache.http.impl.client.HttpClients; | |||||
| 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.math.BigDecimal; | |||||
| import java.net.URLEncoder; | |||||
| import java.security.MessageDigest; | |||||
| import java.security.NoSuchAlgorithmException; | |||||
| import java.text.ParseException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.*; | |||||
| /** | |||||
| * @author: furunxin | |||||
| * @Date: 2020/7/1 17:16 | |||||
| * @Description: 车易付接口对接参数类 | |||||
| */ | |||||
| @Slf4j | |||||
| public class HaiKangWeiShiV2Util { | |||||
| public static final String TOKEN_URL = "https://open.hikyun.com/artemis/oauth/token"; | |||||
| public static final String QUERY_PRICE = "https://open.hikyun.com/artemis/api/v1/charge/getParkingPaymentInfo"; | |||||
| public static final String COUPON_USE = "https://open.hikyun.com/artemis/api/v1/sendCoupon"; | |||||
| public static final String NOTIFY_PAID = "https://open.hikyun.com/artemis/api/v1/charge/payment/notice"; | |||||
| /** | |||||
| * @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 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); | |||||
| if (StringUtils.isBlank(result)) { | |||||
| return null; | |||||
| } | |||||
| JSONObject res = JSON.parseObject(result); | |||||
| String accessToken = res.getString("access_token"); | |||||
| if (null != accessToken ) { | |||||
| return accessToken; | |||||
| }else { | |||||
| throw new MallinkException(500,"haikangv2 access_token error.["+res.getString("error")+"]"+res.getString("error_description")); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 查询停车费 | |||||
| **/ | |||||
| public JSONObject getCarStopFee(WxPark wxPark,String carNumber,String token){ | |||||
| String vendroParams = wxPark.getVendorParams(); | |||||
| JSONObject vp = JSON.parseObject(vendroParams); | |||||
| Map<String,Object> params = new HashMap<String,Object>(); | |||||
| params.put("plateNo", carNumber); | |||||
| params.put("useCoupon", "1"); | |||||
| String retCode = ProcBussiness(QUERY_PRICE, params,token); | |||||
| if (StringUtils.isBlank(retCode)) { | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikangv2 getCarStopInfo error. has no result"); | |||||
| } | |||||
| JSONObject result = JSON.parseObject(retCode); | |||||
| String code = result.getString("code"); | |||||
| if (!code.equals("200") ) { | |||||
| String message = result.getString("msg"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikangv2 getCarStopInfo error.["+code+"]"+message); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 使用优惠券 | |||||
| **/ | |||||
| public JSONObject useCoupon(WxPark wxPark,String token,String carNumber,boolean isTime,Integer cashValue,Date startTime,Date endTime){ | |||||
| String vendroParams = wxPark.getVendorParams(); | |||||
| JSONObject vp = JSON.parseObject(vendroParams); | |||||
| Map<String,Object> params = new HashMap<String,Object>(); | |||||
| params.put("parkCodes", vp.getString("parkCodes")); | |||||
| params.put("generateObj", 1); | |||||
| params.put("plateNo", carNumber); | |||||
| if (isTime) { | |||||
| params.put("couponType", 4); | |||||
| params.put("deductContent", cashValue*60); | |||||
| }else { | |||||
| params.put("couponType", 1); | |||||
| params.put("deductContent", 4); | |||||
| } | |||||
| params.put("startTime", startTime); | |||||
| params.put("endTime", endTime); | |||||
| params.put("couponSource", vp.getString("couponSource")); | |||||
| String retCode = ProcBussiness(COUPON_USE, params,token); | |||||
| if (StringUtils.isBlank(retCode)) { | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikangv2 useCoupon error. has no result"); | |||||
| } | |||||
| JSONObject result = JSON.parseObject(retCode); | |||||
| String code = result.getString("code"); | |||||
| if (!code.equals("200") ) { | |||||
| String message = result.getString("msg"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikangv2 useCoupon error.["+code+"]"+message); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 支付成功通知车场 | |||||
| * @param wxPark | |||||
| * @param orderNo | |||||
| * @param token | |||||
| * @return | |||||
| */ | |||||
| public JSONObject notifyPaid(WxPark wxPark,String parkOrderNo,Integer fee,String token) { | |||||
| String vendroParams = wxPark.getVendorParams(); | |||||
| JSONObject vp = JSON.parseObject(vendroParams); | |||||
| Map param = new HashMap(); | |||||
| param.put("billNo", parkOrderNo);//商户编号 | |||||
| param.put("thirdBillNo", parkOrderNo+wxPark.getId());//我们的单号 | |||||
| param.put("payTime", DateUtils.format(new Date(),DateUtils.DATE_PATTERN_ALL_NOSPACE)); | |||||
| param.put("payType", 3); | |||||
| param.put("payMoney", fee); | |||||
| String retCode = ProcBussiness(NOTIFY_PAID, param,token); | |||||
| if (StringUtils.isBlank(retCode)) { | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikangv2 notifyPaid error. has no result"); | |||||
| } | |||||
| JSONObject result = JSON.parseObject(retCode); | |||||
| String code = result.getString("code"); | |||||
| if (!code.equals("200") ) { | |||||
| String message = result.getString("msg"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikangv2 notifyPaid error.["+code+"]"+message); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| private static String ProcBussiness(String url,Map<String,Object> list,String token) { | |||||
| try { | |||||
| return Proc(url,list,token); | |||||
| } catch (Exception e) { | |||||
| log.error("haikangv2 request error.",e); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private static String Proc(String url, Map<String,Object> pairs,String token) { | |||||
| CloseableHttpClient httpClient = HttpClients.createDefault(); | |||||
| HttpPost httpPost = new HttpPost(url); | |||||
| httpPost.addHeader(HTTP.CONTENT_TYPE,"application/json"); | |||||
| if (!StringUtils.isBlank(token)) { | |||||
| httpPost.addHeader("access_token",token); | |||||
| } | |||||
| if (null != pairs) { | |||||
| try { | |||||
| StringEntity entity = new StringEntity(JSON.toJSONString(pairs),"UTF-8"); | |||||
| entity.setContentType("application/json"); | |||||
| httpPost.setEntity(entity); | |||||
| } catch (Exception e) { | |||||
| log.error(e.getLocalizedMessage(),e); | |||||
| } | |||||
| } | |||||
| long currentTime = System.currentTimeMillis(); | |||||
| StringBuffer requestlog = new StringBuffer(); | |||||
| if (null != pairs) { | |||||
| log.info("haikangweishiv2 httpRequest:[url]"+url+"[params]"+JSON.toJSONString(pairs)); | |||||
| requestlog.append("haikangweishiv2 httpRequest:[url]").append(url).append("[params]").append(JSON.toJSONString(pairs)); | |||||
| }else { | |||||
| log.info("haikangweishiv2 httpRequest:[url]"+url); | |||||
| requestlog.append("haikangweishiv2 httpRequest:[url]").append(url); | |||||
| } | |||||
| HttpResponse response = null; | |||||
| try { | |||||
| response = httpClient.execute(httpPost); | |||||
| } catch (Exception e) { | |||||
| log.error(e.getLocalizedMessage(),e); | |||||
| } | |||||
| long responseCostTime = System.currentTimeMillis()-currentTime; | |||||
| String result = null; | |||||
| //打印StatusLine | |||||
| log.debug("StatusLine: " + response.getStatusLine()); | |||||
| try{ | |||||
| //获取实体 | |||||
| HttpEntity httpEntity= response.getEntity(); | |||||
| result = EntityUtils.toString(httpEntity, "UTF-8"); | |||||
| requestlog.append("[response]").append(result).append("[costTime(ms)]").append(responseCostTime); | |||||
| log.debug(requestlog.toString()); | |||||
| } catch (Exception e) { | |||||
| log.error(e.getLocalizedMessage(),e); | |||||
| } | |||||
| try { //关闭流并释放资源 | |||||
| httpClient.close(); | |||||
| } catch (IOException e) { | |||||
| log.error(e.getLocalizedMessage()); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| private static String ProcLogin(String clientId,String clientSecret) { | |||||
| ArrayList<NameValuePair> list = new ArrayList<NameValuePair>(); | |||||
| list.add(new BasicNameValuePair("client_id", clientId)); | |||||
| list.add(new BasicNameValuePair("client_secret", clientSecret)); | |||||
| return formData(TOKEN_URL,list,null); | |||||
| } | |||||
| private static String formData(String url,List<NameValuePair> pairs,String token) { | |||||
| CloseableHttpClient httpClient = HttpClients.createDefault(); | |||||
| HttpPost httpPost = new HttpPost(url); | |||||
| if (!StringUtils.isBlank(token)) { | |||||
| httpPost.addHeader("access_token",token); | |||||
| } | |||||
| MultipartEntityBuilder builder = MultipartEntityBuilder.create(); | |||||
| if (null != pairs) { | |||||
| for (NameValuePair nvp : pairs) { | |||||
| builder.addPart(nvp.getName(), new StringBody(nvp.getValue(),ContentType.TEXT_PLAIN)); | |||||
| } | |||||
| } | |||||
| HttpEntity entity = builder.build(); | |||||
| httpPost.setEntity(entity); | |||||
| long currentTime = System.currentTimeMillis(); | |||||
| StringBuffer requestlog = new StringBuffer(); | |||||
| if (null != pairs) { | |||||
| log.info("haikangweishiv2 httpRequest start :[url]"+url+"[params]"+JSON.toJSONString(pairs)); | |||||
| requestlog.append("haikangweishiv2 httpRequest:[url]").append(url).append("[params]").append(JSON.toJSONString(pairs)); | |||||
| }else { | |||||
| log.info("haikangweishiv2 httpRequest start :[url]"+url); | |||||
| requestlog.append("haikangweishiv2 httpRequest:[url]").append(url); | |||||
| } | |||||
| HttpResponse response = null; | |||||
| try { | |||||
| response = httpClient.execute(httpPost); | |||||
| } catch (Exception e) { | |||||
| log.error(e.getLocalizedMessage(),e); | |||||
| } | |||||
| long responseCostTime = System.currentTimeMillis()-currentTime; | |||||
| String result = null; | |||||
| //打印StatusLine | |||||
| log.debug("StatusLine: " + response.getStatusLine()); | |||||
| try{ | |||||
| //获取实体 | |||||
| HttpEntity httpEntity= response.getEntity(); | |||||
| result = EntityUtils.toString(httpEntity, "UTF-8"); | |||||
| requestlog.append("[response]").append(result).append("[costTime(ms)]").append(responseCostTime); | |||||
| log.debug(requestlog.toString()); | |||||
| } catch (Exception e) { | |||||
| log.error(e.getLocalizedMessage(),e); | |||||
| } | |||||
| try { //关闭流并释放资源 | |||||
| httpClient.close(); | |||||
| } catch (IOException e) { | |||||
| log.error(e.getLocalizedMessage()); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| } | |||||