winter 3 лет назад
Родитель
Сommit
587554d7ae
5 измененных файлов: 908 добавлений и 0 удалений
  1. +1
    -0
      mallinkService/src/main/java/com/iformall/enums/EnumCarVendor.java
  2. +8
    -0
      mallinkService/src/main/java/com/iformall/service/park/ParkFactory.java
  3. +344
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/jieshunV2/JieShunUtilV2.java
  4. +190
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/jieshunV2/JieShunV2ParkCallbackService.java
  5. +365
    -0
      mallinkService/src/main/java/com/iformall/service/park/impl/jieshunV2/JieShunV2ParkService.java

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

@@ -14,6 +14,7 @@ public enum EnumCarVendor {
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)//深圳市福特智能科技有限公司
;


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

@@ -19,6 +19,8 @@ import com.iformall.service.park.impl.haikangweishi.HaiKangWeiShiParkCallbackSer
import com.iformall.service.park.impl.haikangweishi.HaiKangWeiShiParkService;
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.shangan.ShangAnParkService;
import com.iformall.service.park.impl.tjd.TJDParkService;

@@ -38,6 +40,8 @@ public class ParkFactory {
@Autowired
JieShunParkService jieshunService;
@Autowired
JieShunV2ParkService jieshunV2Service;
@Autowired
HaiKangWeiShiParkService haikangWeishiService;
@Autowired
FuteParkService futeParkService;
@@ -47,6 +51,8 @@ public class ParkFactory {
@Autowired
JieShunParkCallbackService jieshunCallBackService;
@Autowired
JieShunV2ParkCallbackService jieshunV2CallBackService;
@Autowired
HaiKangWeiShiParkCallbackService haikangWeishiCallBackService;
@Autowired
FuteParkCallbackService futeParkCallbackService;
@@ -68,6 +74,7 @@ public class ParkFactory {
parkServiceMap.put(EnumCarVendor.CAR_SHANGAN.getCode(), shangAnService);
parkServiceMap.put(EnumCarVendor.CAR_TJD.getCode(), tjdService);
parkServiceMap.put(EnumCarVendor.CAR_JIESHUN.getCode(), jieshunService);
parkServiceMap.put(EnumCarVendor.CAR_JIESHUN_V2.getCode(), jieshunV2Service);
parkServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI.getCode(), haikangWeishiService);
parkServiceMap.put(EnumCarVendor.CAR_FUTE.getCode(), futeParkService);
return parkServiceMap;
@@ -101,6 +108,7 @@ public class ParkFactory {
}
batchCallBackServiceMap = new ConcurrentHashMap<Integer, ParkBatchCallBackAdapterService>();
batchCallBackServiceMap.put(EnumCarVendor.CAR_JIESHUN.getCode(), jieshunCallBackService);
batchCallBackServiceMap.put(EnumCarVendor.CAR_JIESHUN_V2.getCode(), jieshunV2CallBackService);
batchCallBackServiceMap.put(EnumCarVendor.CAR_HAIKANGWEISHI.getCode(), haikangWeishiCallBackService);
return batchCallBackServiceMap;
}


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

@@ -0,0 +1,344 @@
package com.iformall.service.park.impl.jieshunV2;

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 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.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;


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

@Slf4j
public class JieShunUtilV2 {

public static final String CYF_PARK_ID = "parkingId";
public static final String CYF_CAR_NUMBER = "plate";
public static final String CYF_PARK_NAME = "parking";
public static final String CYF_SYN_ID = "recordOrderId";
public static final String CYF_ENTRANCE_TIME = "inTime";

public static final String CYF_IS_RESULT = "result";
public static final String CYF_ERR_MSG = "strError";
public static final int CYF_SUC = 1;
public static final int CYF_ERR = 0;

public static final String TOKEN_URL = "http://syx.jslife.com.cn/jsaims/login";
public static final String CREATE_ORDER = "http://syx.jslife.com.cn/jsaims/as";
public static final String QUERY_ORDER = "http://syx.jslife.com.cn/jsaims/as";
public static final String GET_COUPON = "http://syx.jslife.com.cn/jsaims/as";
public static final String COUPON_USE = "http://syx.jslife.com.cn/jsaims/as";
public static final String VERIFY_USER = "http://syx.jslife.com.cn/jsaims/as";
public static final String QUERY_PLAN = "http://syx.jslife.com.cn/jsaims/as";
public static final String PLAN_EXECUTE = "http://syx.jslife.com.cn/jsaims/as";

/**
* @description UTC时间转化为本地时间
* @Params [utcTime]
* @return java.util.Date
* @Author furunxin
* @Date 2020/7/8 下午12:45
**/
public static Date utcToLocal(String seconds) throws ParseException {
String format = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date date=sdf.parse(seconds);
return date;
}

public static String getLocalDate(){
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String nowDate = ldt.format(dtf);
return nowDate;
}

public String getToken(WxPark wxPark) {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
String cid = vp.getString("cid");
String userName = vp.getString("usr");
String password = vp.getString("psw");
return getToken(cid,userName,password);
}
private String getToken(String cid,String userName,String password) {
String result = ProcLogin(cid, userName,password);
log.info("jieshunv2 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) {
String msg = res.getString("message");
throw new MallinkException(code,msg);
}
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;
}
public String handleCarNumber(String carNumber) {
if (carNumber.contains("-")) {
return carNumber;
}else {
carNumber = carNumber.substring(0,1)+"-"+carNumber.substring(1, carNumber.length());
return carNumber;
}
}
/**
* 创建订单
* @return
*/
public String createOrder(WxPark wxPark,String cardNumber,String token) {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
Map param = new HashMap();
param.put("businesserCode", vp.get("businesserCode"));//商户编号
param.put("parkCode", wxPark.getParkingId());
param.put("orderType", "VNP");
param.put("carNo", handleCarNumber(cardNumber));
Map map = generateMap("3c.pay.createorderbycarno",param);
log.info("jieshunv2 create order :" + JSON.toJSONString(map));
return ProcBussiness(CREATE_ORDER, wxPark.getParkId(), map, token,vp.getString("version"),vp.getString("signkey"));
}
/**
* 查询停车费
**/
public String getCarStopFee(WxPark wxPark,String orderNo,String token){
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
Map param = new HashMap();
param.put("orderNo", orderNo);//商户编号
Map map = generateMap("3c.pay.queryorder",param);
log.info("jieshunv2 getCarStopFee :" + JSON.toJSONString(map));
return ProcBussiness(QUERY_ORDER, wxPark.getParkId(), map, token,vp.getString("version"),vp.getString("signkey"));
}
/**
* 打折登陆验证
*/
public String verifyuser(WxPark wxPark,String token) {
try {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
Map param = new HashMap();
param.put("userCode", vp.get("loginUser"));//商户编号
MessageDigest md5Tool = MessageDigest.getInstance("MD5");
byte[] md5Data = md5Tool.digest((vp.getString("loginPassword")).getBytes("UTF-8"));
String sn = toHexString(md5Data);
param.put("password", sn.toLowerCase());//优惠券编号
Map map = generateMap("3c.discount.verifyuser",param);
log.info("jieshunv2 verifyuser :" + JSON.toJSONString(map));
return ProcBussiness(VERIFY_USER, wxPark.getParkId(), map, token,vp.getString("version"),vp.getString("signkey"));
} catch (NoSuchAlgorithmException e) {
log.error("jieshunv2 verifyuser error.park:"+wxPark.getId(),e);
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"jieshunv2 verifyuser error.park:"+wxPark.getId()+".error"+e.getMessage());
} catch (UnsupportedEncodingException e) {
log.error("jieshunv2 verifyuser error.park:"+wxPark.getId(),e);
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"jieshunv2 verifyuser error.park:"+wxPark.getId()+".error"+e.getMessage());
}
}
/**
* 查询门店打折方案
*/
public String querySalePlan(WxPark wxPark,String token,String userId) {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
Map param = new HashMap();
param.put("userId", userId);//商户编号
Map map = generateMap("3c.discount.querysaleplan",param);
log.info("jieshunv2 querySalePlan :" + JSON.toJSONString(map));
return ProcBussiness(QUERY_PLAN, wxPark.getParkId(), map, token,vp.getString("version"),vp.getString("signkey"));
}
/**
* 使用打折方案
*/
public String executediscount(WxPark wxPark,String planId,String userId,String carNumber,String token) {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
Map param = new HashMap();
param.put("planId", planId);//商户编号
param.put("userId", userId);//优惠券编号
param.put("carOrCardNo", handleCarNumber(carNumber));//优惠券编号
Map map = generateMap("3c.discount.executediscount",param);
log.info("jieshunv2 executediscount :" + JSON.toJSONString(map));
return ProcBussiness(PLAN_EXECUTE, wxPark.getParkId(), map, token,vp.getString("version"),vp.getString("signkey"));
}
/*token认证登陆**/
private static String ProcLogin(String cid,String user,String password) {
String url = TOKEN_URL +"?cid="+cid+"&usr="+user+"&psw="+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(url,null);
}
/**
* 优惠券使用完毕,0元停车费需调用次接口结清订单
* @param wxPark
* @param planId
* @param userId
* @param carNumber
* @param token
* @return
*/
public String notifyOrderResult(WxPark wxPark,String orderNo,String token) {
String vendroParams = wxPark.getVendorParams();
JSONObject vp = JSON.parseObject(vendroParams);
Map param = new HashMap();
param.put("orderNo", orderNo);//商户编号
param.put("tradeStatus", 0);//优惠券编号
param.put("isCallBack", 0);//优惠券编号
Map map = generateMap("3c.pay.notifyorderresult",param);
log.info("jieshunv2 notifyOrderResult :" + JSON.toJSONString(map));
return ProcBussiness(PLAN_EXECUTE, wxPark.getParkId(), map, token,vp.getString("version"),vp.getString("signkey"));
}
private static String ProcBussiness(String url,String cid,Map<String,Object> param,String token,String version,String signKey) {
try {
MessageDigest md5Tool = MessageDigest.getInstance("MD5");
String p = JSON.toJSONString(param);
byte[] md5Data = md5Tool.digest((p+signKey).getBytes("UTF-8"));
String sn = toHexString(md5Data);
if (url.contains("?")) {
url = url + "&";
}else {
url = url + "?";
}
url = url+"cid="+cid+"&tn="+token+"&sn="+sn+"&v="+version+"&p="+URLEncoder.encode(p, "UTF-8");
//
// ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
// list.add(new BasicNameValuePair("cid", cid));
// list.add(new BasicNameValuePair("v", version));//版本号
// 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,null);
} catch (NoSuchAlgorithmException e) {
log.error("jieshunv2 request error.",e);
} catch (UnsupportedEncodingException e) {
log.error("jieshunv2 request error.",e);
}
return null;
}
private static String toHexString(byte[] bytes) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
buffer.append(String.format("%02X", bytes[i]));
}
return buffer.toString();
}
private static String Proc(String url, List<NameValuePair> pairs) {
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");

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;
}
}

if (null != pairs) {
log.info("jieshunv2 httpRequest:[url]"+url+"[params]"+JSON.toJSONString(pairs));
}else {
log.info("jieshunv2jieshunv2 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;
}
}

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

@@ -0,0 +1,190 @@
package com.iformall.service.park.impl.jieshunV2;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.domain.po.WxCarJSOrder;
import com.iformall.domain.po.WxPark;
import com.iformall.domain.vo.WxCarCYFVo;
import com.iformall.enums.EnumCarVendor;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxCarJSOrderMapper;
import com.iformall.service.WxParkService;
import com.iformall.service.park.ParkBatchCallBackAdapterService;
import com.iformall.service.park.ParkCallBackAdapterService;
import com.iformall.service.park.entity.ParkNotifyParam;
import com.iformall.service.park.impl.BaseParkService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class JieShunV2ParkCallbackService extends BaseParkService implements ParkBatchCallBackAdapterService {
@Autowired
JieShunV2ParkService jieshunParkService;
@Autowired
WxParkService wxParkService;
@Autowired
WxCarJSOrderMapper wxCarJSOrderMapper;
private String handleCarNumber(String carNumber) {
if (StringUtils.isBlank(carNumber)) {
return "空车牌";
}
if (carNumber.contains("-")) {
carNumber = carNumber.replaceAll("-", "");
}
return carNumber;
}

/**
* {dataItems=[{"inTime":"2020-12-09 11:21:15","carNumber":"浙-AF81797","inCarPhoto":"p201127315/NISSP_IMG_PARK_IN/20201209/a9f1130651b9493f8eab64f14afbdd47","isReal":0,"itemId":"a9f1130651b9493f8eab64f14afbdd47","inOperator":"超级管理员","equipName":"东门入口","parkName":"杭州东站西子国际","vehicleInfo":"{\"plateNo\":\"浙-AF81797\",\"plateColor\":\"GREEN\",\"plateBackColor\":0,\"plateWordColor\":0,\"vehicleColor\":null,\"vehicleLogo\":null,\"vehicleModel\":null,\"mainModel\":0,\"subModel\":0,\"vehicleModelTrust\":0,\"mainModelTrust\":0,\"subModelTrust\":0,\"plateNoTrust\":1,\"vehicleLogoTrust\":0,\"vehicleColorTrust\":0}","equipCode":"208202496","parkCode":"p201127315"}], pno=dzxzgj, sn=6C958D99D2769AA16F3A3F06E962263F, tn=-2, ts=20201209112118886, ve=1.0}
*/
@Override
public List<ParkNotifyParam> parseInNoticyParam(Object param) {
Map<String,Object> paramm = (Map<String, Object>) param;
String liststr = (String) paramm.get("dataItems");
JSONArray list = JSONArray.parseArray(liststr);
if (null != list && list.size() > 0 ) {
List<ParkNotifyParam> retList = new ArrayList<ParkNotifyParam>();
for (int i = 0 ; i < list.size() ; i ++) {
Map<String,Object> map = (Map<String, Object>) list.get(i);
ParkNotifyParam ret = parseInNoticyParamSingle(map);
if (null != ret ) {
retList.add(ret);
}
}
return retList;
}
return null;
}
private ParkNotifyParam parseInNoticyParamSingle(Map<String,Object> paramMap) {
String carNumber = paramMap.get("carNumber").toString();
String parkCode = paramMap.get("parkCode").toString();
String parkName = paramMap.get("parkName").toString();
String synId = paramMap.get("itemId").toString();
String entranceTime = paramMap.get("inTime").toString();
ParkNotifyParam p = new ParkNotifyParam();
String realCarNumber = handleCarNumber(carNumber);
p.setCarNumber(realCarNumber);
p.setParkId(parkCode);
p.setParkName(parkName);
p.setSynId(synId);
try {
p.setEntranceTime(JieShunUtilV2.utcToLocal(entranceTime));
} catch (ParseException e) {
log.error("jieshun entranceTime format error",e);
return null;
}
return p;
}

@Override
public List<ParkNotifyParam> parseOutNoticyParam(Object param) {
Map<String,Object> paramm = (Map<String, Object>) param;
String liststr = (String) paramm.get("dataItems");
JSONArray list = JSONArray.parseArray(liststr);
if (null != list && list.size() > 0 ) {
List<ParkNotifyParam> retList = new ArrayList<ParkNotifyParam>();
for (int i = 0 ; i < list.size() ; i ++) {
Map<String,Object> map = (Map<String, Object>) list.get(i);
ParkNotifyParam ret = parseOutNoticyParamSingle(map);
if (null != ret ) {
retList.add(ret);
}
}
return retList;
}
return null;
}
private ParkNotifyParam parseOutNoticyParamSingle(Map<String, Object> paramMap) {
String carNumber = paramMap.get("carNumber").toString();
String parkCode = paramMap.get("parkCode").toString();
String parkName = paramMap.get("parkName").toString();
String synId = paramMap.get("itemId").toString();
String entranceTime = paramMap.get("outTime").toString();
String realCarNumber = handleCarNumber(carNumber);
ParkNotifyParam p = new ParkNotifyParam();
p.setCarNumber(realCarNumber);
p.setParkId(parkCode);
p.setParkName(parkName);
p.setSynId(synId);
try {
p.setEntranceTime(JieShunUtilV2.utcToLocal(entranceTime));
} catch (ParseException e) {
log.error("cyf entranceTime format error",e);
return null;
}
try {
p.setOutTime(JieShunUtilV2.utcToLocal(entranceTime));
} catch (ParseException e) {
log.error("cyf outTime format error",e);
return null;
}
p.setFee(String.valueOf(paramMap.get("ssMoney")));
return p;
}

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

@Override
public List<ParkNotifyParam> parsePaidNoticyParam(Object param) {
Map<String,Object> paramm = (Map<String, Object>) param;
String liststr = (String) paramm.get("dataItems");
JSONArray list = JSONArray.parseArray(liststr);
if (null != list && list.size() > 0 ) {
List<ParkNotifyParam> retList = new ArrayList<ParkNotifyParam>();
for (int i = 0 ; i < list.size() ; i ++) {
Map<String,Object> map = (Map<String, Object>) list.get(i);
ParkNotifyParam ret = parsePaidNoticyParamSingle(map);
if (null != ret ) {
retList.add(ret);
}
}
return retList;
}
return null;
}
JieShunUtilV2 jieshun = new JieShunUtilV2();
private ParkNotifyParam parsePaidNoticyParamSingle(Map<String,Object> vo) {
ParkNotifyParam p = new ParkNotifyParam();
p.setCarNumber(handleCarNumber((String) vo.get("carNumber")));
p.setParkId(String.valueOf(vo.get("parkCode")));
p.setParkOrderId((String) vo.get("itemId"));
p.setSynId((String) vo.get("itemId"));
p.setFee(vo.get("ssMoney").toString());
try {
p.setPayTime(jieshun.utcToLocal((String)vo.get("feesTime")));
} catch (ParseException e) {
e.printStackTrace();
}
return p;
}
}

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

@@ -0,0 +1,365 @@
package com.iformall.service.park.impl.jieshunV2;

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;

/**
*
* token是和ip是一对一绑定,新的ip服务器调捷顺的接口会出现ip不合法,需把ip提供捷顺方,添加白名单。多个服务调捷顺接口共用一个ip情况下,只能共用一套登录获取token机制,各自登录会冲突
* 捷顺参数:
* loginurl=http://syx.jslife.com.cn/jsaims/login
* funcurl=http://syx.jslife.com.cn/jsaims/as
* cid=880075500000002
* usr=880075500000002
* psw=888888
* v=2
* signKey=2f4ce8242b796e4adbb9bdad0794c898
* parkcode=0020200529
*
* https://syx.jslife.com.cn/store/index.html#/auth/login
* 您的登录帐号是880075500000002000019,登录密码为a9A3MYJK
*
* 跳转捷停车小程序参数:(生产环境)
appid:wx24b70f0ad2a9a89a
1>小程序首页
path:pages/index/index
2>小程序订单页(车牌+车场编号 ) path: pages/thirdPayOrder/payOrder?carNo=车牌&parkCode=车场编号
3>小程序订单页(订单编号) path: pages/thirdPayOrderByNo/payOrder?orderNo=订单编号
*/
@Service
public class JieShunV2ParkService 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;
JieShunUtilV2 jieshun = new JieShunUtilV2();
private String getCacheToken(WxPark park) {
String token = RedisCacheUtils.getCacheString(redisTemplate, "carStop:jieshuntokenV2:"+park.getId());
if (StringUtils.isBlank(token)) {
String lockKey = "carStop:jieshuntokenlockV2:"+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(redisTemplate, "carStop:jieshuntokenV2:"+park.getId());
}
private void setCacheToken(WxPark park,String token) {
RedisCacheUtils.cache(redisTemplate, "carStop:jieshuntokenV2:"+park.getId(), token, 3600);
}
/**
* 先去捷顺注册,调用登陆获取令牌,然后根据令牌调用别的接口
* http://ap.jieshun.cn:9088/apply/ 注册信息地址 fumao/iformall2020
*
* 捷顺商户平台:http://merchant.jslife.com.cn/merchant/index.html#/auth/login
* 捷顺门店平台:http://merchant.jslife.com.cn/store/index.html#/auth/login
* 门店商户号 000000008032172000003 密码 ycHqp61Acudxz
*
*
* API对接注意事项:
1、token有效期两个小时,每两小时内登录一次获取token,调业务接口不需要频繁登录用,建议获取一次token存本地缓存,之后从本地获取,两小时内刷新一次,
为避免调业务接口时刚好token被刷新,导致token失效(无效的令牌或令牌已过期),可以做下容错,重新登录获取token或用最新token重新调业务接口。
2、token是和ip是一对一绑定,新的ip服务器调捷顺的接口会出现ip不合法,需把ip提供捷顺方,添加白名单。多个服务调捷顺接口共用一个ip情况下,只能共用一套登录获取token机制,各自登录会冲突。
3、所有接口要带车牌的一律带横杠。格式如:粤-B12345。
4、无效的数据签名是指sn加密方式不对。sn加密方式是对p+signkey进行Md5加密,加密后的字符串大写。
*/
@Override
public ResultData parkInitConfig(WxPark park) throws Exception {
// TODO Auto-generated method stub
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 "jieshunV2";
}

@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 jieshunCarStopFee(paramMap, park,carNumber);
}
private ParkStopFee jieshunCarStopFee(Map<String, String> paramMap, WxPark park,String carNumber) throws Exception{
//如果车牌号是鄂AAAAAA, 为测试车牌
if (carNumber.equals("鄂AAAAAA")) {
return new ParkStopFee("-111",jieshun.utcToLocal("2020-12-16 00:00:00"),jieshun.utcToLocal("2020-12-17 00:00:00"),
"0.01","wx24b70f0ad2a9a89a","payPath",null,"测试车牌,仅测试用",null);
}else if(carNumber.equals("鄂AAAAAB")) {
throw new MallinkException(21000,"车辆未入场");
}
//下订单;
String retCode = jieshun.createOrder(park, carNumber, getCacheToken(park));
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);
}
JSONArray arrays = result.getJSONArray("dataItems");
if (null == arrays || arrays.size() == 0) {
throw new MallinkException(result.getInteger("resultCode"), "jieshun createOrder error. no order result"+carNumber);
}
JSONObject attribute = arrays.getJSONObject(0).getJSONObject("attributes");
Double totalFee = attribute.getDouble("totalFee");
String appId = "wx24b70f0ad2a9a89a";
String parkOrderId = attribute.getString("orderNo");
if (totalFee <= 0 ) {
String _createTime = attribute.getString("startTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss”
String _endTime = attribute.getString("endTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss”
String msg = attribute.getString("retmsg");
if (!StringUtils.isBlank(msg)) {
if (msg.contains("未入场")) {
return new ParkStopFee(null,jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
"0.00",appId,"payPath",null,msg,null);
}else {
//0元订单结清,查询是否用过打折方案,如果用过,则需要调用接口结清订单
Integer used = ParkCacheUtils.getCarCouponUseCacheLock(redisTemplate, EnumCarVendor.CAR_JIESHUN.getMessage(), carNumber);
if (null == used || (null != used && used.intValue() < 1)) {
//未使用停车券
return new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
"0.00",appId,"payPath",null,msg,null);
}else {
return new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
"0.00",appId,"payPath",null,msg,"用券抵扣后账单为0,获得15分钟免费出场时间");
// String notifyResult = jieshun.notifyOrderResult(park, parkOrderId, getCacheToken(park));
// JSONObject notiryRetObj = JSON.parseObject(notifyResult);
// String noticeErrorMsg = notiryRetObj.getString("message");
// if (notiryRetObj.getIntValue("resultCode") == 0){
// JSONArray notiryRetArrays = notiryRetObj.getJSONArray("dataItems");
// if (null != notiryRetArrays && notiryRetArrays.size() == 0 ) {
// JSONObject notifyRetObject = notiryRetArrays.getJSONObject(0).getJSONObject("attributes");
// if(notifyRetObject.getIntValue("retCode") == 0) {
// return new ResultData(new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
// "0.00",appId,"payPath",null,msg,"用券抵扣后账单为0,获得15分钟免费出场时间"));
// }else {
// return new ResultData(new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
// "0.00",appId,"payPath",null,msg,"用券抵扣后账单为0,但是结清订单失败["+noticeErrorMsg+"],无免费出场时间,请下拉刷新"));
// }
// }else {
// return new ResultData(new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
// "0.00",appId,"payPath",null,msg,"用券抵扣后账单为0,但是结清订单失败["+noticeErrorMsg+"],无免费出场时间,请下拉刷新"));
// }
// }else {
// return new ResultData(new ParkStopFee("-999",jieshun.utcToLocal(_createTime),jieshun.utcToLocal(_endTime),
// "0.00",appId,"payPath",null,msg,"用券抵扣后账单为0,但是结清订单失败["+noticeErrorMsg+"],无免费出场时间,请下拉刷新"));
// }
}
}
}
}
String ret = jieshun.getCarStopFee(park, parkOrderId, getCacheToken(park));
JSONObject retObj = JSON.parseObject(ret);
if (retObj.getIntValue("resultCode") == 0){
JSONArray retArrays = retObj.getJSONArray("dataItems");
if (null == retArrays || retArrays.size() == 0 ) {
throw new MallinkException(result.getInteger("resultCode"), "jieshun getCarStopFee error. no order result"+carNumber);
}
JSONObject retObject = retArrays.getJSONObject(0).getJSONObject("attributes");
String createTime = retObject.getString("startTime");//计费时间,格式为“yyyy-MM-dd HH:mi:ss”
String endTime = retObject.getString("endTime");//离场时间,格式为“yyyy-MM-dd HH:mi:ss”
String payPath = "pages/thirdPayOrder/payOrder?carNo="+jieshun.handleCarNumber(carNumber)+"&parkCode="+park.getParkingId();
return new ParkStopFee(parkOrderId,jieshun.utcToLocal(createTime),jieshun.utcToLocal(endTime),
String.valueOf(retObject.getDouble("totalFee")),appId,payPath,null,null,"请支付后15分钟内离场");
}else {
logger.error("jieshunCarStopFee error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),ret);
String msg = retObj.getString("message");
throw new MallinkException(ErrorCode.CYF_STOP_FEE_FAIL.getCode(), "停车费获取失败:"+msg);
}
}

/**
* 使用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(),"当前停车券没有关联停车场优惠券配置[planNo]。"+coupon.getTitle());
}
//String ret = jieshun.getCoupon(park, planNo,userCar.getCUserPhone(), getCacheToken(park));
//打折登陆验证
String ret = jieshun.verifyuser(park, getCacheToken(park));
logger.info("jieshun verifyuser result:"+ret);
JSONObject retObj = JSON.parseObject(ret);
if (retObj.getIntValue("resultCode") == 0){
JSONArray verfyArrays = retObj.getJSONArray("dataItems");
if (null != verfyArrays && verfyArrays.size() > 0 ) {
JSONObject verfy = verfyArrays.getJSONObject(0).getJSONObject("attributes");
String userId = verfy.getString("userId");
//查询门店下打折方案
String queryPlanRet = jieshun.querySalePlan(park, getCacheToken(park), userId);
logger.info("jieshun querySalePlan result:"+queryPlanRet);
JSONObject queryPlantRetObj = JSON.parseObject(queryPlanRet);
if (queryPlantRetObj.getIntValue("resultCode") == 0){
JSONArray planArrays = queryPlantRetObj.getJSONArray("dataItems");
if (null != planArrays && planArrays.size() > 0 ) {
boolean hasPlan = false;
for (int i = 0 ; i < planArrays.size(); i++) {
JSONObject plan = planArrays.getJSONObject(i);
String planId = plan.getJSONObject("attributes").getString("planId");
if (planNo.equals(planId)) {
hasPlan = true;
break;
}
}
if (!hasPlan) {
return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"当前优惠券配置的捷顺编号无效,请联系管理员。"+coupon.getTitle());
}
//使用打折方案
String executeRet = jieshun.executediscount(park, planNo, userId, carNumber, getCacheToken(park));
logger.info("jieshun executediscount result:"+executeRet);
JSONObject executeRetObj = JSON.parseObject(executeRet);
if (executeRetObj.getIntValue("resultCode") == 0){
return new ResultData();
}else {
return new ResultData(executeRetObj.getIntValue("resultCode"),"当前用户使用捷顺停打折方案失败。"+executeRetObj.getString("message"));
}
}else {
return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"捷顺查询门店未查询到打折信息,请联系管理员。"+userCar.getcUserId());
}
}else {
logger.error("jieshun querySalePlan error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),queryPlanRet);
String msg = queryPlantRetObj.getString("message");
return new ResultData(queryPlantRetObj.getIntValue("resultCode"), "捷顺查询门店打折方案失败:"+msg);
}
}else {
return new ResultData(ErrorCode.CYF_STOP_FEE_FAIL.getCode(),"捷顺门店账号登陆失败,请联系管理员。"+userCar.getcUserId());
}
}else {
logger.error("jieshun verifyuser error. paramMap: {} . jieshunResult: {}",JSON.toJSONString(paramMap),ret);
String msg = retObj.getString("message");
return new ResultData(retObj.getIntValue("resultCode"), "当前用户领用到捷顺停车券失败:"+msg);
}
}
@Override
public 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;
}

}

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