diff --git a/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiParkService.java b/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiParkService.java index 2bdefa03d..30ce95985 100644 --- a/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiParkService.java +++ b/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiParkService.java @@ -40,7 +40,16 @@ import com.iformall.utils.RedisLock; /** * 认证平台 https://www.hikyun.com 武汉富茂链客/zfy151431113 + * + * pms.hikyun.com 停车场管理云平台 账号sdw1112131,密码mcgc123456 + * https://open.hikyun.com/1/document/0 + + @配置说明 + clientId,clientSecret 停车场管理系统控制台的。 + productCode: 停车场管理系统产品在云耀注册的id,固定。 + pmsName,pmsPassword : 停车场管理系统pms.hikyun.com 的账号密码 + projectId,ak : 停车场管理系统在云曜推送接口上创建的一个认证标识,联系 超云(开发)给提供 * @author alascor * */ @@ -96,7 +105,7 @@ public class HaiKangWeiShiParkService extends BaseParkService implements ParkAda public ResultData parkInitConfig(WxPark park) throws Exception { Map retMap = new HashMap(); try { - JSONObject retObj = haikang.subscription(park, getCacheToken(park)); + JSONObject retObj = haikang.subscription(park, getCacheToken(park),haikang.getAuthorization(park,getCacheToken(park))); if (retObj.getIntValue("code") == 0){ return new ResultData(); }else { @@ -148,7 +157,7 @@ public class HaiKangWeiShiParkService extends BaseParkService implements ParkAda return new ResultData(21000,"车辆未入场"); } - JSONObject attribute = haikang.getFee(park, carNumber, getCacheToken(park)); + JSONObject attribute = haikang.getFee(park, carNumber, getCacheToken(park),haikang.getAuthorization(park,getCacheToken(park))); String appId = ""; String parkOrderId = attribute.getString("id"); @@ -182,7 +191,7 @@ public class HaiKangWeiShiParkService extends BaseParkService implements ParkAda if (StringUtils.isBlank(planNo)) { return new ResultData(ErrorCode.COUPON_IS_EMPTY.getCode(),"当前停车券没有关联停车场优惠券配置[planNo]。"+coupon.getTitle()); } - JSONObject retObj = haikang.useCoupon(park,planNo,carNumber,orderNo, getCacheToken(park)); + JSONObject retObj = haikang.useCoupon(park,planNo,carNumber,orderNo, getCacheToken(park),haikang.getAuthorization(park,getCacheToken(park))); if (retObj.getIntValue("code") == 0){ return new ResultData(); }else { diff --git a/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiUtil.java b/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiUtil.java index 1ad2b54d7..f35fde5b5 100644 --- a/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiUtil.java +++ b/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/HaiKangWeiShiUtil.java @@ -6,20 +6,35 @@ import com.alibaba.fastjson.JSONObject; import com.iformall.common.ErrorCode; import com.iformall.domain.po.WxPark; import com.iformall.exception.MallinkException; +import com.iformall.service.park.impl.haikangweishi.entity.ChallengeCode; +import com.iformall.utils.HashUtil; + 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.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntity; +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.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; @@ -41,6 +56,8 @@ import java.util.Map; public class HaiKangWeiShiUtil { public static final String TOKEN_URL = "https://open.hikyun.com/artemis/oauth/token"; + public static final String CHALLENGE_CODE = "https://open.hikyun.com/artemis/api/eits/v1/challengeCode"; + public static final String AUTHROZITAION = "https://open.hikyun.com/artemis/api/eits/v1/login"; public static final String GET_FEE = "https://open.hikyun.com/api/pmsc/v1/pay/ quickGetVehicleBill"; public static final String COUPON_USE = "https://open.hikyun.com/api/pmsc/v1/coupon/addition"; public static final String SUBSCRIPTION = "https://open.hikyun.com/api/pmsc/v1/sub/subscription"; @@ -70,43 +87,120 @@ public class HaiKangWeiShiUtil { public String getToken(WxPark wxPark) { String vendroParams = wxPark.getVendorParams(); JSONObject vp = JSON.parseObject(vendroParams); - String clientId = vp.getString("AppKey"); - String clientSecret = vp.getString("SecretKey"); + String clientId = vp.getString("clientId"); + String clientSecret = vp.getString("clientSecret"); return getToken(clientId,clientSecret); } + private ChallengeCode getChallengeCode(WxPark wxPark,String accessToken) { + String vendroParams = wxPark.getVendorParams(); + JSONObject vp = JSON.parseObject(vendroParams); + Map params = new HashMap(); + params.put("name", vp.getString("pmsName"));//pms.hikyun.com 的账号 + params.put("productCode", vp.getString("productCode")); + params.put("type", "1"); + String retCode = ProcBussiness(CHALLENGE_CODE, params,accessToken,null); + if (StringUtils.isBlank(retCode)) { + throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikang getChallengeCode error. has no result"); + } + JSONObject result = JSON.parseObject(retCode); + + Integer errStatus = result.getInteger("status"); + if (null != errStatus) { + throw new MallinkException(errStatus,"haikang getChallengeCode error.["+result.getString("error")+"]"+result.getString("message")); + } + + if (!result.getString("code").equals("200") ) { + String message = result.getString("msg"); + throw new MallinkException(result.getInteger("code"), "haikang getChallengeCode error."+message); + } + JSONObject attribute = result.getJSONObject("data"); + if (null == attribute) { + throw new MallinkException(result.getInteger("code"), "haikang getChallengeCode error. no result"); + } + return new ChallengeCode(attribute.getString("pwdStatus"),attribute.getString("codeId"),attribute.getString("salt"),attribute.getString("vCode")); + } + + private static String entryPmsPassword(String password,String salt,String vCode) { + return HashUtil.sha256(HashUtil.sha256(password+salt)+vCode); + } + + //使用后不能再次使用,并且有很短的过期时间 + public String getAuthorization(WxPark wxPark,String accessToken) { + String vendroParams = wxPark.getVendorParams(); + JSONObject vp = JSON.parseObject(vendroParams); + ChallengeCode challengeCode = getChallengeCode(wxPark,accessToken); + Map params = new HashMap(); + params.put("name", vp.getString("pmsName"));//pms.hikyun.com 的账号 + params.put("productCode", vp.getString("productCode")); + params.put("type", "1"); + params.put("codeId", challengeCode.getCodeId()); + params.put("password", entryPmsPassword(vp.getString("pmsPassword"),challengeCode.getSalt(),challengeCode.getVCode())); + String retCode = ProcBussiness(AUTHROZITAION, params,accessToken,null); + if (StringUtils.isBlank(retCode)) { + throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikang getAuthorization error. has no result"); + } + JSONObject result = JSON.parseObject(retCode); + + Integer errStatus = result.getInteger("status"); + if (null != errStatus) { + throw new MallinkException(errStatus,"haikang getAuthorization error.["+result.getString("error")+"]"+result.getString("message")); + } + + if (!result.getString("code").equals("200") ) { + String message = result.getString("msg"); + throw new MallinkException(result.getInteger("code"), "haikang getAuthorization error."+message); + } + JSONObject attribute = result.getJSONObject("data"); + if (null == attribute) { + throw new MallinkException(result.getInteger("code"), "haikang getAuthorization error. no result"); + } + return attribute.getString("Authorization"); + + } + private String getToken(String clientId,String clientSecret) { String result = ProcLogin(clientId, clientSecret); - log.info("haikang token clientId:"+clientId+" clientSecret:"+clientSecret+" result: "+result); if (StringUtils.isBlank(result)) { return null; } JSONObject res = JSON.parseObject(result); - Integer code = res.getInteger("code"); - if (null == code || code.intValue() != 0) { - String msg = res.getString("msg"); - throw new MallinkException(code,msg); + Integer errStatus = res.getInteger("status"); + if (null != errStatus) { + throw new MallinkException(errStatus,"haikang access_token error.["+res.getString("error")+"]"+res.getString("message")); + } + + String accessToken = res.getString("access_token"); + if (null != accessToken ) { + return accessToken; + }else { + throw new MallinkException(500,"haikang access_token error.["+res.getString("error")+"]"+res.getString("error_description")); } - return res.getString("access_token"); } /** * 查询停车费 3.5.5 快速获取账单接口 * @return */ - public JSONObject getFee(WxPark wxPark,String carNumber,String token) { + public JSONObject getFee(WxPark wxPark,String carNumber,String token,String Authrozitaion) { String vendroParams = wxPark.getVendorParams(); JSONObject vp = JSON.parseObject(vendroParams); - ArrayList list = new ArrayList(); - list.add(new BasicNameValuePair("chargeSource", "THIRD"));//商户编号 - list.add(new BasicNameValuePair("parkId", wxPark.getParkingId())); - list.add(new BasicNameValuePair("plateNo", carNumber)); - String retCode= ProcBussiness(GET_FEE, list, token); + Map params = new HashMap(); + params.put("chargeSource", "THIRD");//商户编号 + params.put("parkId", wxPark.getParkingId()); + params.put("plateNo", carNumber); + String retCode= ProcBussiness(GET_FEE, params, token,Authrozitaion); if (StringUtils.isBlank(retCode)) { throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikang getFee error. has no result"); } JSONObject result = JSON.parseObject(retCode); - if (result.getInteger("code") != 0 ) { + + Integer errStatus = result.getInteger("status"); + if (null != errStatus) { + throw new MallinkException(errStatus,"haikang getFee error.["+result.getString("error")+"]"+result.getString("message")); + } + + if (!result.getString("code").equals("200") ) { String message = result.getString("msg"); throw new MallinkException(result.getInteger("code"), "haikang getFee error."+message); } @@ -126,20 +220,26 @@ public class HaiKangWeiShiUtil { 完成一次优惠缴费 * 使用优惠券 3.5.9.1接口进行车牌和优惠信息绑定优惠券后,车辆出场时会自动抵扣 **/ - public JSONObject useCoupon(WxPark wxPark,String couponNo,String carNumber,String orderNo,String token){ + public JSONObject useCoupon(WxPark wxPark,String couponNo,String carNumber,String orderNo,String token,String Authrozitaion){ String vendroParams = wxPark.getVendorParams(); JSONObject vp = JSON.parseObject(vendroParams); - ArrayList list = new ArrayList(); + Map params = new HashMap(); Map couponmap = new HashMap(); couponmap.put("plateNo", carNumber); couponmap.put("ruleId", couponNo); - list.add(new BasicNameValuePair("coupons", "["+JSON.toJSONString(couponmap)+"]") );//商户编号 - String retCode = ProcBussiness(COUPON_USE, list,token); + params.put("coupons", "["+JSON.toJSONString(couponmap)+"]");//商户编号 + String retCode = ProcBussiness(COUPON_USE, params,token,Authrozitaion); if (StringUtils.isBlank(retCode)) { throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikang useCoupon error. has no result"); } JSONObject result = JSON.parseObject(retCode); - if (result.getInteger("code") != 0 ) { + + Integer errStatus = result.getInteger("status"); + if (null != errStatus) { + throw new MallinkException(errStatus,"haikang useCoupon error.["+result.getString("error")+"]"+result.getString("message")); + } + + if (!result.getString("code").equals("200") ) { String message = result.getString("msg"); throw new MallinkException(result.getInteger("code"), "haikang useCoupon error."+message); } @@ -159,20 +259,26 @@ public class HaiKangWeiShiUtil { * @param clientSecret * @return */ - public JSONObject subscription(WxPark wxPark,String token){ + public JSONObject subscription(WxPark wxPark,String token,String Authrozitaion){ String vendroParams = wxPark.getVendorParams(); JSONObject vp = JSON.parseObject(vendroParams); - ArrayList list = new ArrayList(); - list.add(new BasicNameValuePair("partnerAppKey", vp.getString("AppKey")));//商户编号 - list.add(new BasicNameValuePair("projectId", vp.getString("projectId"))); - list.add(new BasicNameValuePair("eventTypes", "[\"771760131\",\"771760134\"]")); - list.add(new BasicNameValuePair("subUrl", vp.getString("subUrl"))); - String retCode = ProcBussiness(SUBSCRIPTION, list,token); + Map params = new HashMap(); + params.put("partnerAppKey", vp.getString("ak"));//商户编号 + params.put("projectId", vp.getString("projectId")); + params.put("eventTypes", "[\"771760131\",\"771760134\"]"); + params.put("subUrl", vp.getString("subUrl")); + String retCode = ProcBussiness(SUBSCRIPTION, params,token,Authrozitaion); if (StringUtils.isBlank(retCode)) { throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(), "haikang subscription error. has no result"); } JSONObject result = JSON.parseObject(retCode); - if (result.getInteger("code") != 0 ) { + + Integer errStatus = result.getInteger("status"); + if (null != errStatus) { + throw new MallinkException(errStatus,"haikang subscription error.["+result.getString("error")+"]"+result.getString("message")); + } + + if (!result.getString("code").equals("200") ) { String message = result.getString("msg"); throw new MallinkException(result.getInteger("code"), "haikang subscription error."+message); } @@ -184,12 +290,13 @@ public class HaiKangWeiShiUtil { ArrayList list = new ArrayList(); list.add(new BasicNameValuePair("client_id", clientId)); list.add(new BasicNameValuePair("client_secret", clientSecret)); - return Proc(TOKEN_URL,list,null,null); + return formData(TOKEN_URL,list,null,null); } - private static String ProcBussiness(String url,ArrayList list,String token) { + + + private static String ProcBussiness(String url,Map list,String token,String authorization) { try { - String authorization = ""; return Proc(url,list,token,authorization); } catch (Exception e) { log.error("haikang request error.",e); @@ -197,13 +304,10 @@ public class HaiKangWeiShiUtil { return null; } - private static String Proc(String url, List pairs,String token,String authorization) { + private static String Proc(String url, Map pairs,String token,String authorization) { 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 (!StringUtils.isBlank(token)) { httpPost.addHeader("access_token",token); } @@ -212,15 +316,13 @@ public class HaiKangWeiShiUtil { } if (null != pairs) { - HttpEntity en; - try { - en = new UrlEncodedFormEntity(pairs, HTTP.UTF_8); - httpPost.setEntity(en); + try { + StringEntity entity = new StringEntity(JSON.toJSONString(pairs)); + entity.setContentType("application/json"); + httpPost.setEntity(entity); } catch (UnsupportedEncodingException e) { log.error(e.getLocalizedMessage(),e); - return null; } - } if (null != pairs) { @@ -255,4 +357,56 @@ public class HaiKangWeiShiUtil { } return result; } + + private static String formData(String url,List pairs,String token,String authorization) { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(url); + if (!StringUtils.isBlank(token)) { + httpPost.addHeader("access_token",token); + } + if (!StringUtils.isBlank(authorization)) { + httpPost.addHeader("Authorization",authorization); + } + 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); + + if (null != pairs) { + log.info("haikangweishi httpRequest:[url]"+url+"[params]"+JSON.toJSONString(pairs)); + }else { + log.info("haikangweishi 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; + } } diff --git a/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/entity/ChallengeCode.java b/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/entity/ChallengeCode.java new file mode 100644 index 000000000..a36022e32 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/park/impl/haikangweishi/entity/ChallengeCode.java @@ -0,0 +1,15 @@ +package com.iformall.service.park.impl.haikangweishi.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class ChallengeCode { + + private String pwdStatus; + private String codeId; + private String salt; + private String vCode; + +}