| @@ -276,7 +276,8 @@ public class WxCarController extends BaseController { | |||
| notes = "ETCP:={\"etcpToken\":\"string(ETCP专用)\",\"carNumber\":\"string\",\"couponOrderId\"=\"String\"}\n" + | |||
| "TJD:{\"carNumber\":\"string\",\"tradeId\":\"string\",\"accountId\":\"string\",\"couponOrderId\":\"string\"}\n" + | |||
| "ShangAn:{\"carNumber\":\"string\",\"couponOrderId\":\"string\"}\n" + | |||
| "BoLink:{\"carNumber\":\"string\",\"orderId\":\"string\",\"couponOrderId\":\"string\"}\n" | |||
| "BoLink:{\"carNumber\":\"string\",\"orderId\":\"string\",\"couponOrderId\":\"string\"}\n" + | |||
| "jieshun:{\"carNumber\":\"string\",\"orderId\":\"string\",\"couponOrderId\":\"string\",\"jsOrderId\":\"string\"}\n}" | |||
| ) | |||
| @PostMapping("/getCoupon") | |||
| public ResultData getCoupon(@RequestBody Map<String, String> paramMap) { | |||
| @@ -315,6 +316,15 @@ public class WxCarController extends BaseController { | |||
| List<WxCouponOrderCarCVo> list = wxCouponOrderService.carListCUserVo(userCarQ); | |||
| if (null != list && list.size() > 0) { | |||
| userCar = list.get(0); | |||
| WxCUserBasicInfo user; | |||
| try { | |||
| user = getCacheMember(); | |||
| if (null != user) { | |||
| userCar.setCUserPhone(user.getPhone()); | |||
| } | |||
| } catch (Exception e) { | |||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "当前用户缓存查询失败"); | |||
| } | |||
| } | |||
| EnumCarVendor vendor = EnumCarVendor.getEnum(park.getVendorType()); | |||
| @@ -1,10 +1,19 @@ | |||
| package com.iformall.controller; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.enums.EnumPayWay; | |||
| import com.iformall.pay.WxPayment; | |||
| import com.iformall.service.WxRefundOrderService; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import java.util.Map; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| @@ -21,12 +30,23 @@ public class HomeController { | |||
| @Value("${spring.mail.username}") | |||
| private String from; | |||
| @Autowired | |||
| private WxRefundOrderService wxRefundOrderService; | |||
| @ApiOperation("获取后端版本号") | |||
| @GetMapping("/version") | |||
| public ResultData version() { | |||
| return new ResultData(version); | |||
| } | |||
| // @ApiOperation("获取后端版本号") | |||
| // @GetMapping("/ttt") | |||
| // public ResultData ttttttt() { | |||
| // String json = "<xml><return_code>SUCCESS</return_code><appid><![CDATA[wxed2f44705544b892]]></appid><mch_id><![CDATA[1511925291]]></mch_id><sub_appid><![CDATA[wx649b3be73c1afe47]]></sub_appid><sub_mch_id><![CDATA[1513691501]]></sub_mch_id><nonce_str><![CDATA[e247be6b46746354de7b5bd84f56e83d]]></nonce_str><req_info><![CDATA[Ndaz8Fj4VUkxnD9iQ2ghD0YcMhVA1AojXftGoSJ5pE03/BhSaOuypQF8/XIZc3NWcIm0xOhTxw4AhqoFmyDi+ZsDGbPKSYlaBI1prdbXr8ZGvGxVReTHS93ePZNtqpWofvtNt2h/1EOPt+a9E03Og02rvAtLlnq6RKjwTLOlIUxWXJMvtsCtpXKvcWMxRx+8pn42Barx6B2D0lM+39Vmi/qjZpQMsMdpKvl5DHkRl0QNFyaD1lQF6Ehe3B0gJhvWRI/EUkWw9lt+XPN0O3li9XPqBXTvD8DI/syYB/PtWcuKAYVdcVHzVm0uf2yM4YwDdFHWRezdozoOgeeU85NDpH7Q6kNYRqYoIg8z/WzdNRTysmHV+hUjzDZlYG7I6FmRfMoefg5kti7QkOAfDSCUJ8YAj/EzK6sYQeJqabcX6HwZzWyNVAJ9DYJquPa3T+ZFpUM5lW657Xj3DxZDwlX7TyWqSammhqWU34MRlEZ4d832pMgiQeGU2HxyKeBvzo6wwIPz0uEeqHyFSmy7x2EWeAb3SzNBkDT8u7XF6gC7zQzwM8+eoSdkjq7XZV/hPd4ZfsD7a8Y19U14KiizsfA6s33sNcKpBefSVLMfX7shFEGubnpY7bGQyPSl/xCmtgtoZlea2G9luLOlLRtppHRPmDhLvBMr8fmZbHKkRvWIO2Ec8WkhQSXKt2b85hrcP+fYx1/3u614GF+k5OSs7bmbSIydoh2L0Eh7SwgtFw8cYiR7BggAWhrHz739vYpHccKaLx+Rh39+GAtWYmzdOMEjBgScEY00lzfbpc1uruaoKDTwqxWCDfm1WFIs6XnWQh3qZCDHG6Qh+38TOtoi/2FJo509BsRcLEliVOzaSLat/gqVXQ+xYm76bSaxjA8ITdltiNTInZFTg5OJ3nCj63bvULc0Jf1KeXocHQxJQfNHleOl6GwlOIu91BEjy6Tjt5SJ2GYrTTtfb4FiE6yvvwoX08THBrheu958CcQcfD7HY8wJ76BrWIVHqnzaUvnG5aoP8VWLChx7TD+RihjX9nS18K1o8lc/5ySR57MDmPcgwLQ=]]></req_info></xml>"; | |||
| // wxRefundOrderService.notify(WxPayment.xmlToMap(json), EnumPayWay.getEnum(EnumPayWay.PAY_WAY_WECHAT.getCode())); | |||
| // return new ResultData(version); | |||
| // } | |||
| } | |||
| @@ -185,6 +185,13 @@ public class BaseMyBatisConfiguration { | |||
| wxCouponActionLogSharding.setRule(EnumShardingRule.HASH.getCode()); | |||
| shardingList.add(wxCouponActionLogSharding); | |||
| ShardingSphere wxCarJSOrderSharding = new ShardingSphere(); | |||
| wxCarJSOrderSharding.setColumn("car_number"); | |||
| wxCarJSOrderSharding.setTableName("wx_car_js_order"); | |||
| wxCarJSOrderSharding.setCount(100); | |||
| wxCarJSOrderSharding.setRule(EnumShardingRule.HASH.getCode()); | |||
| shardingList.add(wxCarJSOrderSharding); | |||
| //初始化 | |||
| @@ -0,0 +1,24 @@ | |||
| package com.iformall.domain.po; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import com.iformall.domain.po.base.TenantEntity; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import lombok.ToString; | |||
| import java.util.Date; | |||
| @TableName(value = "wx_car_js_order") | |||
| @Data | |||
| @ToString(callSuper = true) | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class WxCarJSOrder extends TenantEntity { | |||
| private static final long serialVersionUID = 4859824437127457878L; | |||
| private Long id; | |||
| private String carNumber; | |||
| private String orderId; | |||
| private Integer status; | |||
| private Date createTime; | |||
| private Date updateTime; | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package com.iformall.domain.vo; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.iformall.domain.po.WxCouponOrder; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| @@ -14,5 +15,8 @@ public class WxCouponOrderCarCVo extends WxCouponOrderCVo { | |||
| @io.swagger.annotations.ApiModelProperty(value="couponFreeId",name="couponFreeId") | |||
| private Integer couponFreeId; | |||
| @TableField(exist = false) | |||
| private String cUserPhone; | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| package com.iformall.mapper; | |||
| import com.iformall.common.CommonMapper; | |||
| import com.iformall.domain.po.WxCarJSOrder; | |||
| /** | |||
| * @author gongbiao | |||
| */ | |||
| public interface WxCarJSOrderMapper extends CommonMapper<WxCarJSOrder, String> { | |||
| WxCarJSOrder getOneOrder(WxCarJSOrder order); | |||
| void updateStatus(WxCarJSOrder order); | |||
| } | |||
| @@ -4,20 +4,47 @@ import java.text.ParseException; | |||
| import java.util.Date; | |||
| 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.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.ParkCallBackAdapterService; | |||
| import com.iformall.service.park.entity.ParkNotifyParam; | |||
| import com.iformall.service.park.impl.BaseParkService; | |||
| import com.iformall.service.park.impl.cyf.CYFUtil; | |||
| import com.iformall.service.park.impl.tjd.TJDUtil; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| @Slf4j | |||
| @Service | |||
| public class JieShunParkCallbackService extends BaseParkService implements ParkCallBackAdapterService { | |||
| @Autowired | |||
| JieShunParkService jieshunParkService; | |||
| @Autowired | |||
| WxParkService wxParkService; | |||
| @Autowired | |||
| WxCarJSOrderMapper wxCarJSOrderMapper; | |||
| private String handleCarNumber(String carNumber) { | |||
| if (carNumber.contains("-")) { | |||
| carNumber = carNumber.replaceAll("-", ""); | |||
| } | |||
| return carNumber; | |||
| } | |||
| /** | |||
| * { | |||
| @@ -45,47 +72,85 @@ public class JieShunParkCallbackService extends BaseParkService implements ParkC | |||
| @Override | |||
| public ParkNotifyParam parseInNoticyParam(Object param) { | |||
| Map<String, Object> paramMap = (Map<String, Object>) param; | |||
| String carNumber = paramMap.get(JieShunUtil.CYF_CAR_NUMBER).toString(); | |||
| String cyfParkId = paramMap.get(CYFUtil.CYF_PARK_ID).toString(); | |||
| String parkName = paramMap.get(CYFUtil.CYF_PARK_NAME).toString(); | |||
| String synId = paramMap.get(CYFUtil.CYF_SYN_ID).toString(); | |||
| String entranceTime = paramMap.get(CYFUtil.CYF_ENTRANCE_TIME).toString(); | |||
| 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(); | |||
| p.setCarNumber(carNumber); | |||
| p.setParkId(cyfParkId); | |||
| String realCarNumber = handleCarNumber(carNumber); | |||
| p.setCarNumber(realCarNumber); | |||
| p.setParkId(parkCode); | |||
| p.setParkName(parkName); | |||
| p.setSynId(synId); | |||
| try { | |||
| p.setEntranceTime(CYFUtil.utcToLocal(entranceTime)); | |||
| p.setEntranceTime(JieShunUtil.utcToLocal(entranceTime)); | |||
| } catch (ParseException e) { | |||
| log.error("cyf entranceTime format error",e); | |||
| return null; | |||
| } | |||
| //下订单; | |||
| WxPark pq = new WxPark(); | |||
| pq.setVendorType(EnumCarVendor.CAR_JIESHUN.getCode()); | |||
| pq.setParkId(parkCode); | |||
| WxPark park = wxParkService.getByObj(pq); | |||
| String retCode = jieshunParkService.createOrder(park, carNumber); | |||
| if (StringUtils.isBlank(retCode)) { | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "jieshun createOrder error. has no result"); | |||
| } | |||
| JSONObject result = JSON.parseObject(retCode); | |||
| if (result.getInteger("resultCode") != 0 ) { | |||
| String message = result.getString("message"); | |||
| throw new MallinkException(result.getInteger("resultCode"), "jieshun createOrder error."+message); | |||
| } | |||
| String parkOrderId = result.getString("orderNo"); | |||
| //记录当前车牌的订单号 | |||
| WxCarJSOrder order = new WxCarJSOrder(); | |||
| order.setId(IdWorker.get().nextId()); | |||
| order.setCarNumber(realCarNumber); | |||
| order.updateTenantInfo(park); | |||
| order.setCreateTime(new Date()); | |||
| order.setUpdateTime(new Date()); | |||
| order.setStatus(1); | |||
| order.setOrderId(parkOrderId); | |||
| wxCarJSOrderMapper.insert(order); | |||
| return p; | |||
| } | |||
| @Override | |||
| public ParkNotifyParam parseOutNoticyParam(Object param) { | |||
| WxCarCYFVo vo = (WxCarCYFVo) param; | |||
| Map<String, Object> paramMap = (Map<String, Object>) param; | |||
| 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(vo.getPlate()); | |||
| p.setParkId(String.valueOf(vo.getParkingId())); | |||
| p.setParkName(vo.getRecordOrderId()); | |||
| p.setSynId(vo.getRecordOrderId()); | |||
| p.setCarNumber(realCarNumber); | |||
| p.setParkId(parkCode); | |||
| p.setParkName(parkName); | |||
| p.setSynId(synId); | |||
| try { | |||
| p.setEntranceTime(TJDUtil.dateOutFormat.parse(vo.getInInfo().getTime())); | |||
| p.setEntranceTime(JieShunUtil.utcToLocal(entranceTime)); | |||
| } catch (ParseException e) { | |||
| log.error("cyf entranceTime format error",e); | |||
| return null; | |||
| } | |||
| try { | |||
| p.setOutTime(TJDUtil.dateOutFormat.parse(vo.getOutInfo().getTime())); | |||
| p.setOutTime(JieShunUtil.utcToLocal(entranceTime)); | |||
| } catch (ParseException e) { | |||
| log.error("cyf outTime format error",e); | |||
| return null; | |||
| } | |||
| p.setFee(String.valueOf(vo.getPayInfoList().getActualFee())); | |||
| p.setFee(String.valueOf(paramMap.get("ssMoney"))); | |||
| WxCarJSOrder order = new WxCarJSOrder(); | |||
| order.setCarNumber(realCarNumber); | |||
| wxCarJSOrderMapper.updateStatus(order); | |||
| return p; | |||
| } | |||
| @@ -98,12 +163,12 @@ public class JieShunParkCallbackService extends BaseParkService implements ParkC | |||
| public ParkNotifyParam parsePaidNoticyParam(Object param) { | |||
| Map vo = (Map) param; | |||
| ParkNotifyParam p = new ParkNotifyParam(); | |||
| p.setCarNumber((String) vo.get("plate")); | |||
| p.setParkId(String.valueOf(vo.get("parkId"))); | |||
| p.setCarNumber((String) vo.get("carNumber")); | |||
| p.setParkId(String.valueOf(vo.get("parkCode"))); | |||
| p.setParkOrderId((String) vo.get("orderNo")); | |||
| p.setSynId((String) vo.get("orderNo")); | |||
| p.setFee(vo.get("fee").toString()); | |||
| p.setPayTime((Date) vo.get("payTime")); | |||
| p.setSynId((String) vo.get("itemId")); | |||
| p.setFee(vo.get("totalFee").toString()); | |||
| p.setPayTime((Date) vo.get("tradeTime")); | |||
| return p; | |||
| } | |||
| @@ -7,21 +7,30 @@ 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.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.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.impl.BaseParkService; | |||
| import com.iformall.service.park.impl.util.ParkHelper; | |||
| import com.iformall.utils.RedisCacheUtils; | |||
| import com.iformall.utils.RedisLock; | |||
| @Service | |||
| public class JieShunParkService extends BaseParkService implements ParkAdapterService { | |||
| @@ -31,48 +40,80 @@ public class JieShunParkService extends BaseParkService implements ParkAdapterSe | |||
| @Autowired | |||
| ParkHelper parkHelper; | |||
| JieShunUtil cyf = new JieShunUtil(); | |||
| @Autowired | |||
| @Qualifier("objectCommonRedisTemplate") | |||
| RedisTemplate<String, Object> baseCUserTokenRedisTemplate; | |||
| @Autowired | |||
| RedisLock redisLock; | |||
| @Autowired | |||
| WxCarJSOrderMapper wxCarJSOrderMapper; | |||
| JieShunUtil jieshun = new JieShunUtil(); | |||
| private String getCacheToken(WxPark park) { | |||
| // String token = RedisCacheUtils.getCacheString(baseCUserTokenRedisTemplate, "carStop:jieshuntoken:"+park.getId()); | |||
| // if (StringUtils.isBlank(token)) { | |||
| // String lockKey = "carStop:jieshuntokenlock:"+park.getTenantId(); | |||
| // long time = System.currentTimeMillis() + 2000; | |||
| // String timeStr = String.valueOf(time); | |||
| // if (redisLock.lock2(lockKey, timeStr)) { | |||
| // token = jieshun.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(baseCUserTokenRedisTemplate, "carStop:jieshuntoken:"+park.getId()); | |||
| return null; | |||
| } | |||
| private void setCacheToken(WxPark park,String token) { | |||
| RedisCacheUtils.cache(baseCUserTokenRedisTemplate, "carStop:jieshuntoken:"+park.getId(), token, 3600); | |||
| } | |||
| /** | |||
| * 先去捷顺注册,调用登陆获取令牌,然后根据令牌调用别的接口 | |||
| * api.jieshun.cn:9088/apply/ 注册信息地址 fumao/iformall2020 | |||
| * | |||
| * 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 String initLogin(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) throws Exception{ | |||
| return null; | |||
| } | |||
| /** | |||
| * 下订单 | |||
| */ | |||
| public String createOrder(WxPark park,String carNumber) { | |||
| return jieshun.createOrder(park, carNumber, getCacheToken(park)); | |||
| } | |||
| @Override | |||
| public String bindCar(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) throws Exception{ | |||
| return jieshunBindCar(paramMap,park,member); | |||
| return "jieshun"; | |||
| } | |||
| /** | |||
| * @description 车易付会员车辆信息注册 | |||
| * @Params [paramMap, park, wxCUser] | |||
| * @return com.iformall.common.ResultData | |||
| * @Author furunxin | |||
| * @Date 2020/7/8 下午10:23 | |||
| **/ | |||
| private String jieshunBindCar(Map<String, String> paramMap, WxPark park,WxCUserBasicInfo member) throws Exception { | |||
| String carNumber = paramMap.get("carNumber"); | |||
| if (StringUtils.isBlank(carNumber)) { | |||
| logger.error("carNumber为空"); | |||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "carNumber为空"); | |||
| } | |||
| String params = park.getVendorParams(); | |||
| JSONObject objParams = JSON.parseObject(params); | |||
| String token = objParams.getString("token"); | |||
| int feeGroupId = objParams.getIntValue("feeGroupId"); | |||
| String ret = cyf.registerCar(token,park.getNumber(),feeGroupId,park.getParkingId(),carNumber,null,member.getNickName()); | |||
| JSONObject retObj = JSON.parseObject(ret); | |||
| if (retObj.getIntValue("result") == 1){ | |||
| return retObj.get("localPersonId").toString(); | |||
| }else { | |||
| logger.error("cyfBindCar error. paramMap: {} . cyfResult: {}",JSON.toJSONString(paramMap),ret); | |||
| String msg = retObj.getString("strError"); | |||
| throw new MallinkException(ErrorCode.CAR_BIND_FAIL.getCode(), "绑车牌失败:"+msg); | |||
| //return new ResultData(, "绑车牌失败", retObj); | |||
| } | |||
| } | |||
| @Override | |||
| public void unbindCar(Map<String, String> paramMap, WxPark park, WxCUserBasicInfo member) throws Exception{ | |||
| @@ -81,66 +122,76 @@ public class JieShunParkService extends BaseParkService implements ParkAdapterSe | |||
| @Override | |||
| public ResultData carStopFee(Map<String, String> paramMap, WxPark park) throws Exception{ | |||
| return cyfCarStopFee(paramMap, park); | |||
| return jieshunCarStopFee(paramMap, park); | |||
| } | |||
| private ResultData cyfCarStopFee(Map<String, String> paramMap, WxPark park) throws Exception{ | |||
| private ResultData jieshunCarStopFee(Map<String, String> paramMap, WxPark park) throws Exception{ | |||
| String carNumber = paramMap.get("carNumber"); | |||
| if (StringUtils.isBlank(carNumber)) { | |||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "carNumber为空"); | |||
| } | |||
| String params = park.getVendorParams(); | |||
| JSONObject objParams = JSON.parseObject(params); | |||
| String token = objParams.getString("token"); | |||
| String ret = cyf.getCarStopFee(token,park.getParkingId(),carNumber); | |||
| WxCarJSOrder order = new WxCarJSOrder(); | |||
| order.setCarNumber(carNumber); | |||
| order.setStatus(1); | |||
| WxCarJSOrder jsorder = wxCarJSOrderMapper.getOneOrder(order); | |||
| if (null == jsorder) { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "停车费获取失败:该车牌订单未查询到!"); | |||
| } | |||
| String ret = jieshun.getCarStopFee(park, jsorder.getOrderId(), getCacheToken(park)); | |||
| JSONObject retObj = JSON.parseObject(ret); | |||
| if (retObj.getIntValue("result") == 1){ | |||
| if (retObj.getIntValue("resultCode") == 0){ | |||
| return new ResultData(retObj); | |||
| }else { | |||
| logger.error("cyfCarStopFee error. paramMap: {} . cyfResult: {}",JSON.toJSONString(paramMap),ret); | |||
| String msg = retObj.getString("strError"); | |||
| logger.error("jieshunCarStopFee error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),ret); | |||
| String msg = retObj.getString("message"); | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "停车费获取失败:"+msg); | |||
| } | |||
| } | |||
| /** | |||
| * 优惠券支付流程:(1):调取openapi/getFee路径获取当前停车费,入参:plate,parkingId,token | |||
| (2):调用地址:http://wechat.cheyifu2016.com/fm-pay/#/transit?encodeURIComponent('orderNo=123&couponFee=2&actualFee=20') | |||
| 注: 详细参考接口文档参数 | |||
| * @param token | |||
| * @param orderNo | |||
| * @param couponFee | |||
| * @param actualFee | |||
| * 使用停车券。 先获取停车券,再使用。 | |||
| * @return | |||
| */ | |||
| @Override | |||
| public ResultData useCoupon(Map<String, String> paramMap, WxPark park, WxCouponOrderCarCVo userCar,WxCoupon coupon,String carNumber) throws Exception{ | |||
| String params = park.getVendorParams(); | |||
| JSONObject objParams = JSON.parseObject(params); | |||
| String token = objParams.getString("token"); | |||
| //先获取停车费,然后再提交停车费 | |||
| String ret = cyf.getCarStopFee(token,park.getParkingId(),carNumber); | |||
| String orderNo = objParams.getString("jsOrderId"); | |||
| 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()); | |||
| } | |||
| String ret = jieshun.getCoupon(park, userCar.getCUserPhone(), getCacheToken(park)); | |||
| logger.info("jieshun getCoupon result:"+ret); | |||
| JSONObject retObj = JSON.parseObject(ret); | |||
| if (retObj.getIntValue("result") == 1){ | |||
| String orderId = retObj.getString("orderId"); | |||
| if (StringUtils.isBlank(orderId)) { | |||
| logger.error("cyfCarStopFee error. paramMap: {} . cyfResult: {}",JSON.toJSONString(paramMap),ret); | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "车易付停车费查询未返回订单编号:"+orderId); | |||
| if (retObj.getIntValue("resultCode") == 0){ | |||
| JSONArray couponArrays = retObj.getJSONArray("dataItems"); | |||
| if (null != couponArrays && couponArrays.size() > 0 ) { | |||
| JSONObject coupoo = couponArrays.getJSONObject(0); | |||
| String couponNo = coupoo.getString("couponsNo"); | |||
| String rret = jieshun.useCoupon(park, couponNo, orderNo, getCacheToken(park)); | |||
| logger.info("jieshun useCoupon["+orderNo+"] result:"+rret); | |||
| JSONObject rretObj = JSON.parseObject(rret); | |||
| if (rretObj.getIntValue("resultCode") == 0){ | |||
| return new ResultData(); | |||
| }else { | |||
| return new ResultData(rretObj.getIntValue("resultCode"),"当前用户使用捷顺停车券失败。"+rretObj.getString("message")); | |||
| } | |||
| }else { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"当前用户未领用到捷顺停车券。"+userCar.getcUserId()); | |||
| } | |||
| if (!coupon.getUnit().equals(EnumCouponUnit.MONEY.getCode())) { | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "车易付只能支持金额券,不能使用小时券:"+orderId); | |||
| } | |||
| int fee = retObj.getInteger("fee"); | |||
| int amount = Integer.parseInt(coupon.getPriceStr()); | |||
| Map retmap = new HashMap(); | |||
| retmap.put("orderNo", orderId); | |||
| retmap.put("couponFee", amount); | |||
| retmap.put("actualFee", fee-amount); | |||
| return new ResultData(); | |||
| }else { | |||
| logger.error("cyfCarStopFee error. paramMap: {} . cyfResult: {}",JSON.toJSONString(paramMap),ret); | |||
| String msg = retObj.getString("strError"); | |||
| return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "停车费获取失败:"+msg); | |||
| logger.error("jieshun getCoupon error. paramMap: {} . cyfResult: {}",JSON.toJSONString(paramMap),ret); | |||
| String msg = retObj.getString("message"); | |||
| return new ResultData(retObj.getIntValue("resultCode"), "当前用户领用到捷顺停车券失败:"+msg); | |||
| } | |||
| } | |||
| @@ -1,25 +1,38 @@ | |||
| package com.iformall.service.park.impl.jieshun; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.iformall.domain.po.WxPark; | |||
| 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.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.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; | |||
| @@ -44,6 +57,15 @@ public class JieShunUtil { | |||
| public static final int CYF_SUC = 1; | |||
| public static final int CYF_ERR = 0; | |||
| public static final String TOKEN_URL = "http://www.jslife.com.cn/jsaims/login"; | |||
| public static final String CREATE_ORDER = ""; | |||
| public static final String QUERY_ORDER = ""; | |||
| public static final String GET_COUPON = ""; | |||
| public static final String COUPON_USE = ""; | |||
| //会员车辆信息注册接口地址 | |||
| public static final String REGISTER_CAR_URL = "http://open.cheyifu2016.com:8892/openapi/personCar"; | |||
| @@ -81,66 +103,153 @@ public class JieShunUtil { | |||
| return nowDate; | |||
| } | |||
| public String getToken(WxPark wxPark) { | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| String cid = wxPark.getParkingId(); | |||
| String userName = vp.getString("userName"); | |||
| String password = vp.getString("password"); | |||
| return getToken(cid,userName,password); | |||
| } | |||
| private String getToken(String cid,String userName,String password) { | |||
| String result = ProcLogin(cid, userName,password); | |||
| log.info("jieshun token cid:"+cid+" userName:"+userName+" password:"+password+" result: "+result); | |||
| if (StringUtils.isBlank(result)) { | |||
| return null; | |||
| } | |||
| JSONObject res = JSON.parseObject(result); | |||
| Integer code = res.getInteger("resultCode"); | |||
| if (null == code || code.intValue() != 0) { | |||
| return null; | |||
| } | |||
| return res.getString("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; | |||
| } | |||
| private String handleCarNumber(String carNumber) { | |||
| if (carNumber.contains("-")) { | |||
| return carNumber; | |||
| }else { | |||
| carNumber = carNumber.substring(0,1)+carNumber.substring(1, carNumber.length()-1); | |||
| return carNumber; | |||
| } | |||
| } | |||
| /** | |||
| * @description 会员车辆信息注册 | |||
| * @Params [token, carport, feeGroupId, parkingId, plates, personId, personName] | |||
| * @return java.lang.String | |||
| * @Author furunxin | |||
| * @Date 2020/7/8 下午10:12 | |||
| * 创建订单 | |||
| * @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.get("businesserCode"));//商户编号 | |||
| param.put("parkCode", wxPark.getParkId()); | |||
| param.put("orderType", "VNP"); | |||
| param.put("carNo", handleCarNumber(cardNumber)); | |||
| Map map = generateMap("3c.pay.createorderbycarno",param); | |||
| log.info("jieshun create order :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(CREATE_ORDER, wxPark.getParkingId(), map, token); | |||
| } | |||
| /** | |||
| * 查询停车费 | |||
| **/ | |||
| public String registerCar(String token,int carport,int feeGroupId,String parkingId,String plates,Long personId,String personName){ | |||
| String[] plate = new String[1]; | |||
| plate[0] = plates; | |||
| Map<String, Object> paramMap = new HashMap<>(); | |||
| paramMap.put("token",token); | |||
| paramMap.put("parkingId",Integer.valueOf(parkingId)); | |||
| paramMap.put("beginTime",getLocalDate()); | |||
| paramMap.put("endTime",getLocalDate()); | |||
| paramMap.put("feeGroupId",feeGroupId); | |||
| paramMap.put("lotNumber",carport); | |||
| //paramMap.put("personId",personId); | |||
| paramMap.put("personName",personName); | |||
| paramMap.put("plates",plate); | |||
| String result = Proc(REGISTER_CAR_URL, paramMap); | |||
| return result; | |||
| public String getCarStopFee(WxPark wxPark,String orderNo,String token){ | |||
| Map param = new HashMap(); | |||
| param.put("orderNo", orderNo);//商户编号 | |||
| Map map = generateMap("3c.pay.queryorder",param); | |||
| log.info("jieshun getCarStopFee :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(QUERY_ORDER, wxPark.getParkingId(), map, token); | |||
| } | |||
| /** | |||
| * @description 根据车牌号获取停车费 | |||
| * @Params [token, parkingId, plates] | |||
| * @return java.lang.String | |||
| * @Author furunxin | |||
| * @Date 2020/7/12 下午3:51 | |||
| * 获取优惠券 | |||
| **/ | |||
| public String getCarStopFee(String token,String parkingId,String plates){ | |||
| Map<String, Object> paramMap = new HashMap<>(); | |||
| paramMap.put("token ",token); | |||
| paramMap.put("parkingId",Integer.valueOf(parkingId)); | |||
| paramMap.put("plates",plates); | |||
| paramMap.put("carOutTime",0); | |||
| String result = Proc(GET_CAR_STOPFEE, paramMap); | |||
| return result; | |||
| public String getCoupon(WxPark wxPark,String phone,String token){ | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| String couponNo = vp.getString("couponNo"); | |||
| Map param = new HashMap(); | |||
| param.put("businesserCode", vp.get("businesserCode"));//商户编号 | |||
| param.put("planNo", couponNo);//优惠券编号 | |||
| param.put("tel", phone);//商户编号 | |||
| Map map = generateMap("3c.coupons.receive.coupons",param); | |||
| log.info("jieshun getCoupon :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(GET_COUPON, wxPark.getParkingId(), map, token); | |||
| } | |||
| /** | |||
| * @description 解绑车辆 | |||
| * @param token | |||
| * @param parkingId | |||
| * @param personId | |||
| * @return | |||
| */ | |||
| public String unbindCar(String token,String parkingId,String vendorPersonId) { | |||
| Map<String, Object> paramMap = new HashMap<>(); | |||
| paramMap.put("token ",token); | |||
| paramMap.put("parkingId",Integer.valueOf(parkingId)); | |||
| paramMap.put("personId",Integer.valueOf(vendorPersonId)); | |||
| String result = Proc(UNBIND_CAR, paramMap); | |||
| return result; | |||
| * 使用优惠券 | |||
| **/ | |||
| public String useCoupon(WxPark wxPark,String couponNo,String orderNo,String token){ | |||
| String vendroParams = wxPark.getVendorParams(); | |||
| JSONObject vp = JSON.parseObject(vendroParams); | |||
| Map param = new HashMap(); | |||
| param.put("businesserCode", vp.get("businesserCode"));//商户编号 | |||
| param.put("couponsNo", couponNo);//优惠券编号 | |||
| param.put("orderNo", orderNo);//商户编号 | |||
| param.put("parkCode", wxPark.getParkId()); | |||
| Map map = generateMap("3c.coupons.use.coupons",param); | |||
| log.info("jieshun useCoupon :" + JSON.toJSONString(map)); | |||
| return ProcBussiness(COUPON_USE, wxPark.getParkingId(), map, token); | |||
| } | |||
| private static String Proc(String url, Map<String, Object> paramMap) { | |||
| private static String ProcLogin(String cid,String user,String password) { | |||
| ArrayList<NameValuePair> list = new ArrayList<NameValuePair>(); | |||
| list.add(new BasicNameValuePair("cid", cid)); | |||
| list.add(new BasicNameValuePair("usr", user)); | |||
| list.add(new BasicNameValuePair("psw",password)); | |||
| return Proc(TOKEN_URL,list); | |||
| } | |||
| 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.getBytes("UTF-8")); | |||
| String sn = toHexString(md5Data); | |||
| ArrayList<NameValuePair> list = new ArrayList<NameValuePair>(); | |||
| list.add(new BasicNameValuePair("cid", cid)); | |||
| list.add(new BasicNameValuePair("v", "1.0"));//版本号 | |||
| list.add(new BasicNameValuePair("p",p)); | |||
| list.add(new BasicNameValuePair("sn",sn)); | |||
| if (!StringUtils.isBlank(token)) { | |||
| list.add(new BasicNameValuePair("tn",token)); | |||
| } | |||
| return Proc(url,list); | |||
| } catch (NoSuchAlgorithmException e) { | |||
| log.error("jieshun request error.",e); | |||
| } catch (UnsupportedEncodingException e) { | |||
| log.error("jieshun 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 Proc(String url, List<NameValuePair> pairs) { | |||
| CloseableHttpClient httpClient = HttpClients.createDefault(); | |||
| HttpPost httpPost = new HttpPost(url); | |||
| @@ -148,16 +257,16 @@ public class JieShunUtil { | |||
| httpPost.addHeader("Accept", "application/json"); | |||
| httpPost.addHeader("Accept-Encoding", "UTF-8"); | |||
| String jsonstr = JSON.toJSONString(paramMap); | |||
| log.info("请求报文:"+jsonstr); | |||
| try { | |||
| StringEntity se = new StringEntity(jsonstr, Consts.UTF_8); | |||
| se.setContentType("application/json"); | |||
| se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,"UTF-8")); | |||
| httpPost.setEntity(se); | |||
| } catch (Exception e) { | |||
| log.error(e.getMessage()); | |||
| if (null != pairs) { | |||
| HttpEntity en; | |||
| try { | |||
| en = new UrlEncodedFormEntity(pairs, HTTP.UTF_8); | |||
| httpPost.setEntity(en); | |||
| } catch (UnsupportedEncodingException e) { | |||
| log.error(e.getLocalizedMessage(),e); | |||
| return null; | |||
| } | |||
| } | |||
| HttpResponse response = null; | |||
| @@ -177,7 +286,7 @@ public class JieShunUtil { | |||
| result = EntityUtils.toString(httpEntity, "UTF-8"); | |||
| log.debug(result); | |||
| } catch (Exception e) { | |||
| log.error(e.getLocalizedMessage()); | |||
| log.error(e.getLocalizedMessage(),e); | |||
| } | |||
| try { //关闭流并释放资源 | |||
| @@ -0,0 +1,55 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
| <mapper namespace="com.iformall.mapper.WxCarJSOrderMapper"> | |||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxCarJSOrder"> | |||
| <id column="id" jdbcType="BIGINT" property="id"/> | |||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId"/> | |||
| <result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId"/> | |||
| <result column="car_number" jdbcType="VARCHAR" property="carNumber"/> | |||
| <result column="order_id" jdbcType="VARCHAR" property="orderId"/> | |||
| <result column="status" jdbcType="INTEGER" property="status"/> | |||
| <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> | |||
| <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> | |||
| </resultMap> | |||
| <sql id="allColumns"> | |||
| `id`,`car_number`,`tenant_id`,`parent_tenant_id`,`order_id`,`status`,`create_time`,`update_time` | |||
| </sql> | |||
| <sql id="dynamicWhereConditions"> | |||
| where 1 = 1 | |||
| <if test=" null != id "> | |||
| and `id` = #{id} | |||
| </if> | |||
| <if test=" null != tenantId and '' != tenantId"> | |||
| and `tenant_id` = #{tenantId} | |||
| </if> | |||
| <if test=" null != parentTenantId and '' != parentTenantId"> | |||
| and `parent_tenant_id` = #{parentTenantId} | |||
| </if> | |||
| <if test=" null != carNumber and '' != carNumber"> | |||
| and `car_number` = #{carNumber} | |||
| </if> | |||
| <if test=" null != status and '' != status"> | |||
| and `status` = #{status} | |||
| </if> | |||
| </sql> | |||
| <select id="getOneOrder" parameterType="com.iformall.domain.po.WxCarJSOrder" resultMap="BaseResultMap"> | |||
| select | |||
| <include refid="allColumns"/> | |||
| from wx_car_js_order | |||
| <include refid="dynamicWhereConditions"/> | |||
| order by create_time desc | |||
| limit 0, 1 | |||
| </select> | |||
| <update id="updateStatus" parameterType="com.iformall.domain.po.WxCarJSOrder"> | |||
| update wx_car_js_order set status = 2, update_time=now() where car_number = #{carNumber} and status = 1 | |||
| </update> | |||
| </mapper> | |||