mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 02:55:04 +08:00
add 联联平台相关工具类
This commit is contained in:
@@ -32,6 +32,24 @@ public class LianLianController extends BaseController {
|
||||
private LianLianService lianLianService;
|
||||
|
||||
|
||||
@PostMapping("/pushStationInfo")
|
||||
public RestApiResponse<?> pushStationInfo(@RequestBody QueryStationInfoDTO dto) {
|
||||
logger.info("推送联联平台充电站信息 params:{}", JSONObject.toJSONString(dto));
|
||||
RestApiResponse<?> response = null;
|
||||
try {
|
||||
lianLianService.pushStationInfo(Long.parseLong(dto.getStationID()));
|
||||
response = new RestApiResponse<>();
|
||||
}catch (BusinessException e) {
|
||||
logger.error("推送联联平台充电站信息 error",e);
|
||||
response = new RestApiResponse<>(e.getCode(), e.getMessage());
|
||||
}catch (Exception e) {
|
||||
logger.error("推送联联平台充电站信息 error", e);
|
||||
response = new RestApiResponse<>(e);
|
||||
}
|
||||
logger.info("推送联联平台充电站信息 result:{}", response);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 联联平台查询充电站信息
|
||||
* http://localhost:8080/LianLian/query_stations_info
|
||||
@@ -58,6 +76,7 @@ public class LianLianController extends BaseController {
|
||||
|
||||
/**
|
||||
* 联联平台查询充电站状态信息
|
||||
* http://localhost:8080/LianLian/query_station_status
|
||||
* @param StationIDs
|
||||
* @return
|
||||
*/
|
||||
@@ -84,6 +103,8 @@ public class LianLianController extends BaseController {
|
||||
|
||||
/**
|
||||
* 查询统计信息
|
||||
* http://localhost:8080/LianLian/query_station_stats
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@@ -107,6 +128,7 @@ public class LianLianController extends BaseController {
|
||||
|
||||
/**
|
||||
* 请求设备认证
|
||||
* http://localhost:8080/LianLian/query_equip_auth
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@@ -130,6 +152,7 @@ public class LianLianController extends BaseController {
|
||||
|
||||
/**
|
||||
* 请求启动充电
|
||||
* http://localhost:8080/LianLian/query_start_charge
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@@ -153,6 +176,7 @@ public class LianLianController extends BaseController {
|
||||
|
||||
/**
|
||||
* 查询充电状态
|
||||
* http://localhost:8080/LianLian/query_equip_charge_status/{startChargeSeq}
|
||||
* @param startChargeSeq
|
||||
* @return
|
||||
*/
|
||||
@@ -176,6 +200,7 @@ public class LianLianController extends BaseController {
|
||||
|
||||
/**
|
||||
* 请求停止充电
|
||||
* http://localhost:8080/LianLian/query_stop_charge
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -9,15 +9,12 @@ import com.jsowell.common.core.domain.ykc.TransactionRecordsData;
|
||||
import com.jsowell.common.core.redis.RedisCache;
|
||||
import com.jsowell.common.enums.ykc.OrderStatusEnum;
|
||||
import com.jsowell.common.exception.BusinessException;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.DictUtils;
|
||||
import com.jsowell.common.util.JWTUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.YKCUtils;
|
||||
import com.jsowell.common.util.*;
|
||||
import com.jsowell.common.util.http.HttpUtils;
|
||||
import com.jsowell.common.util.id.SnUtils;
|
||||
import com.jsowell.common.util.id.SnowflakeIdWorker;
|
||||
import com.jsowell.common.util.ip.AddressUtils;
|
||||
import com.jsowell.common.util.lianlian.LianLianUtils;
|
||||
import com.jsowell.netty.command.ykc.IssueQRCodeCommand;
|
||||
import com.jsowell.netty.command.ykc.ProofreadTimeCommand;
|
||||
import com.jsowell.netty.handler.HeartbeatRequestHandler;
|
||||
@@ -29,14 +26,7 @@ import com.jsowell.pile.domain.PileBillingDetail;
|
||||
import com.jsowell.pile.domain.PileBillingTemplate;
|
||||
import com.jsowell.pile.domain.PileStationInfo;
|
||||
import com.jsowell.pile.domain.WxpayCallbackRecord;
|
||||
import com.jsowell.pile.dto.BasicPileDTO;
|
||||
import com.jsowell.pile.dto.BatchCreatePileDTO;
|
||||
import com.jsowell.pile.dto.ImportBillingTemplateDTO;
|
||||
import com.jsowell.pile.dto.QueryOrderDTO;
|
||||
import com.jsowell.pile.dto.QueryPileDTO;
|
||||
import com.jsowell.pile.dto.QueryStationDTO;
|
||||
import com.jsowell.pile.dto.RefundableWxPayOrderData;
|
||||
import com.jsowell.pile.dto.WeixinPayDTO;
|
||||
import com.jsowell.pile.dto.*;
|
||||
import com.jsowell.pile.mapper.MemberBasicInfoMapper;
|
||||
import com.jsowell.pile.mapper.PileBillingTemplateMapper;
|
||||
import com.jsowell.pile.service.IOrderBasicInfoService;
|
||||
@@ -55,6 +45,8 @@ import com.jsowell.service.MemberService;
|
||||
import com.jsowell.service.OrderService;
|
||||
import com.jsowell.service.PileRemoteService;
|
||||
import com.jsowell.service.PileService;
|
||||
import com.jsowell.thirdparty.domain.StationInfo;
|
||||
import com.jsowell.thirdparty.service.LianLianService;
|
||||
import com.jsowell.wxpay.common.WeChatPayParameter;
|
||||
import com.jsowell.wxpay.dto.AppletTemplateMessageSendDTO;
|
||||
import com.jsowell.wxpay.dto.WeChatRefundDTO;
|
||||
@@ -73,13 +65,7 @@ import org.springframework.util.StopWatch;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@ActiveProfiles("dev")
|
||||
@SpringBootTest(classes = JsowellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@@ -154,6 +140,13 @@ public class SpringBootTestController {
|
||||
@Autowired
|
||||
private IPileAuthCardService pileAuthCardService;
|
||||
|
||||
@Autowired
|
||||
private LianLianService lianLianService;
|
||||
|
||||
static final String MAC_KEY = "53TtFpc4gdVZbF3x";
|
||||
|
||||
static final String ALGORITHM_MAC = "HmacMD5";
|
||||
|
||||
@Test
|
||||
public void testupdateElecAmount() {
|
||||
orderBasicInfoService.updateElecAmount();
|
||||
@@ -165,6 +158,70 @@ public class SpringBootTestController {
|
||||
System.out.println(pileAuthCard);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLianLian() throws Exception {
|
||||
// Long stationId = 2L;
|
||||
// // 通过id查询站点相关信息
|
||||
// PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(stationId);
|
||||
// // 组装联联平台所需要的数据格式
|
||||
// StationInfo info = StationInfo.builder()
|
||||
// .StationID(String.valueOf(stationId))
|
||||
// .OperatorID(Constants.OPERATORID_LIANLIAN)
|
||||
// .EquipmentOwnerID(Constants.OPERATORID_LIANLIAN)
|
||||
// .StationName(pileStationInfo.getStationName())
|
||||
// .IsAloneApply(Integer.valueOf(pileStationInfo.getAloneApply()))
|
||||
// .IsPublicParkingLot(Integer.valueOf(pileStationInfo.getPublicParking()))
|
||||
// .CountryCode(pileStationInfo.getCountryCode())
|
||||
// .AreaCode(pileStationInfo.getAreaCode())
|
||||
// .Address(pileStationInfo.getAddress())
|
||||
// .ServiceTel(pileStationInfo.getServiceTel())
|
||||
// .StationType(Integer.valueOf(pileStationInfo.getStationType()))
|
||||
// .StationStatus(Integer.valueOf(pileStationInfo.getStationStatus()))
|
||||
// .ParkNums(Integer.valueOf(pileStationInfo.getParkNums()))
|
||||
// .StationLng(new BigDecimal(pileStationInfo.getStationLng()))
|
||||
// .StationLat(new BigDecimal(pileStationInfo.getStationLat()))
|
||||
// .Construction(Integer.valueOf(pileStationInfo.getConstruction()))
|
||||
// .OpenAllDay(Integer.valueOf(pileStationInfo.getOpenAllDay()))
|
||||
// // .MinElectricityPrice()
|
||||
// // .ElectricityFee()
|
||||
// // .ServiceFee()
|
||||
// .ParkFree(Integer.valueOf(pileStationInfo.getParkFree()))
|
||||
// // .ParkFee()
|
||||
// .Payment(pileStationInfo.getPayment())
|
||||
// .SupportOrder(Integer.valueOf(pileStationInfo.getSupportOrder()))
|
||||
// // .equipmentInfos()
|
||||
// // .ParkFeeType()
|
||||
// .ToiletFlag(Integer.valueOf(pileStationInfo.getToiletFlag()))
|
||||
// .StoreFlag(Integer.valueOf(pileStationInfo.getStoreFlag()))
|
||||
// .RestaurantFlag(Integer.valueOf(pileStationInfo.getRestaurantFlag()))
|
||||
// .LoungeFlag(Integer.valueOf(pileStationInfo.getLoungeFlag()))
|
||||
// .CanopyFlag(Integer.valueOf(pileStationInfo.getCanopyFlag()))
|
||||
// .PrinterFlag(Integer.valueOf(pileStationInfo.getPrinterFlag()))
|
||||
// .BarrierFlag(Integer.valueOf(pileStationInfo.getBarrierFlag()))
|
||||
// .ParkingLockFlag(Integer.valueOf(pileStationInfo.getParkingLockFlag()))
|
||||
//
|
||||
// .build();
|
||||
|
||||
// List<EquipmentInfo> pileList = lianLianService.getPileList(pileStationInfo);
|
||||
// if (CollectionUtils.isNotEmpty(pileList)) {
|
||||
// info.setEquipmentInfos(pileList); // 充电设备信息列表
|
||||
// }
|
||||
|
||||
String url = "http://testdataexchange.evchargeonline.com:82/shevcs/v1/" + "notification_stationInfo";
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("OperatorID", "MA1JLFUU8");
|
||||
json.put("OperatorSecret", "Nh62XxllR5OjAzFj");
|
||||
// json.put("StationInfo", info);
|
||||
|
||||
LianLianGetTokenDTO dto = new LianLianGetTokenDTO();
|
||||
dto.setOperatorId("987654321");
|
||||
dto.setOperatorSecret("1234567890abcdef");
|
||||
String token = lianLianService.getToken(dto);
|
||||
System.out.println("token:" + token);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRefundForBalance() {
|
||||
BigDecimal refundAmount = new BigDecimal("2");
|
||||
|
||||
@@ -33,6 +33,8 @@ public class Constants {
|
||||
|
||||
public static final String partnerId = "1632405339"; // 商户号Id
|
||||
|
||||
public static final String OPERATORID_LIANLIAN = "MA1JLFUU8";
|
||||
|
||||
// public static final String APP_ID = "wxbb3e0d474569481d"; // 举视充电网 wxbb3e0d474569481d
|
||||
//
|
||||
// public static final String APP_SECRET = "bbac689f4654b209de4d6944808ec80b"; // 举视充电网 bbac689f4654b209de4d6944808ec80b
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.jsowell.common.util;/**
|
||||
* TODO
|
||||
*
|
||||
* @author JS-ZZA
|
||||
* @date 2023/5/6 14:22
|
||||
*/public class LianLianUtils {
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
*/
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Cryptos {
|
||||
|
||||
private static final String AES = "AES";
|
||||
private static final String AES_CBC = "AES/CBC/PKCS5Padding";
|
||||
private static final String HMACSHA1 = "HmacSHA1";
|
||||
|
||||
private static final String DEFAULT_URL_ENCODING = "UTF-8";
|
||||
private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401
|
||||
private static final int DEFAULT_AES_KEYSIZE = 128;
|
||||
private static final int DEFAULT_IVSIZE = 16;
|
||||
|
||||
private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
|
||||
|
||||
private static SecureRandom random = new SecureRandom();
|
||||
|
||||
//-- HMAC-SHA1 funciton --//
|
||||
/**
|
||||
* 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key HMAC-SHA1密钥
|
||||
*/
|
||||
public static byte[] hmacSha1(byte[] input, byte[] key) {
|
||||
try {
|
||||
SecretKey secretKey = new SecretKeySpec(key, HMACSHA1);
|
||||
Mac mac = Mac.getInstance(HMACSHA1);
|
||||
mac.init(secretKey);
|
||||
return mac.doFinal(input);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验HMAC-SHA1签名是否正确.
|
||||
*
|
||||
* @param expected 已存在的签名
|
||||
* @param input 原始输入字符串
|
||||
* @param key 密钥
|
||||
*/
|
||||
public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {
|
||||
byte[] actual = hmacSha1(input, key);
|
||||
return Arrays.equals(expected, actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成HMAC-SHA1密钥,返回字节数组,长度为160位(20字节).
|
||||
* HMAC-SHA1算法对密钥无特殊要求, RFC2401建议最少长度为160位(20字节).
|
||||
*/
|
||||
public static byte[] generateHmacSha1Key() {
|
||||
try {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(HMACSHA1);
|
||||
keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE);
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
return secretKey.getEncoded();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
//-- AES funciton --//
|
||||
|
||||
/**
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
*/
|
||||
public static String aesEncrypt(String input) {
|
||||
try {
|
||||
return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static String aesEncrypt(String input, String key) {
|
||||
try {
|
||||
return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key)));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static byte[] aesEncrypt(byte[] input, byte[] key) {
|
||||
return aes(input, key, Cipher.ENCRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param iv 初始向量
|
||||
*/
|
||||
public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
|
||||
return aes(input, key, iv, Cipher.ENCRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
*/
|
||||
public static String aesDecrypt(String input) {
|
||||
try {
|
||||
return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static String aesDecrypt(String input, String key) {
|
||||
try {
|
||||
return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static byte[] aesDecrypt(byte[] input, byte[] key) {
|
||||
return aes(input, key, Cipher.DECRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param iv 初始向量
|
||||
*/
|
||||
public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
|
||||
return aes(input, key, iv, Cipher.DECRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
|
||||
*
|
||||
* @param input 原始字节数组
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
|
||||
*/
|
||||
private static byte[] aes(byte[] input, byte[] key, int mode) {
|
||||
try {
|
||||
SecretKey secretKey = new SecretKeySpec(key, AES);
|
||||
Cipher cipher = Cipher.getInstance(AES);
|
||||
cipher.init(mode, secretKey);
|
||||
return cipher.doFinal(input);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
|
||||
*
|
||||
* @param input 原始字节数组
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param iv 初始向量
|
||||
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
|
||||
*/
|
||||
private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
|
||||
try {
|
||||
SecretKey secretKey = new SecretKeySpec(key, AES);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
Cipher cipher = Cipher.getInstance(AES_CBC);
|
||||
cipher.init(mode, secretKey, ivSpec);
|
||||
return cipher.doFinal(input);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
|
||||
*/
|
||||
public static String generateAesKeyString() {
|
||||
return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
|
||||
*/
|
||||
public static byte[] generateAesKey() {
|
||||
return generateAesKey(DEFAULT_AES_KEYSIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AES密钥,可选长度为128,192,256位.
|
||||
*/
|
||||
public static byte[] generateAesKey(int keysize) {
|
||||
try {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
|
||||
keyGenerator.init(keysize);
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
return secretKey.getEncoded();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
|
||||
*/
|
||||
public static byte[] generateIV() {
|
||||
byte[] bytes = new byte[DEFAULT_IVSIZE];
|
||||
random.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
*/
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class Digests {
|
||||
|
||||
private static final String SHA1 = "SHA-1";
|
||||
private static final String MD5 = "MD5";
|
||||
|
||||
private static SecureRandom random = new SecureRandom();
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
*/
|
||||
public static byte[] md5(byte[] input) {
|
||||
return digest(input, MD5, null, 1);
|
||||
}
|
||||
public static byte[] md5(byte[] input, int iterations) {
|
||||
return digest(input, MD5, null, iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(byte[] input) {
|
||||
return digest(input, SHA1, null, 1);
|
||||
}
|
||||
|
||||
public static byte[] sha1(byte[] input, byte[] salt) {
|
||||
return digest(input, SHA1, salt, 1);
|
||||
}
|
||||
|
||||
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
|
||||
return digest(input, SHA1, salt, iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对字符串进行散列, 支持md5与sha1算法.
|
||||
*/
|
||||
private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||
|
||||
if (salt != null) {
|
||||
digest.update(salt);
|
||||
}
|
||||
|
||||
byte[] result = digest.digest(input);
|
||||
|
||||
for (int i = 1; i < iterations; i++) {
|
||||
digest.reset();
|
||||
result = digest.digest(result);
|
||||
}
|
||||
return result;
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机的Byte[]作为salt.
|
||||
*
|
||||
* @param numBytes byte数组的大小
|
||||
*/
|
||||
public static byte[] generateSalt(int numBytes) {
|
||||
Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
|
||||
|
||||
byte[] bytes = new byte[numBytes];
|
||||
random.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行md5散列.
|
||||
*/
|
||||
public static byte[] md5(InputStream input) throws IOException {
|
||||
return digest(input, MD5);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(InputStream input) throws IOException {
|
||||
return digest(input, SHA1);
|
||||
}
|
||||
|
||||
private static byte[] digest(InputStream input, String algorithm) throws IOException {
|
||||
try {
|
||||
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
|
||||
int bufferLength = 8 * 1024;
|
||||
byte[] buffer = new byte[bufferLength];
|
||||
int read = input.read(buffer, 0, bufferLength);
|
||||
|
||||
while (read > -1) {
|
||||
messageDigest.update(buffer, 0, read);
|
||||
read = input.read(buffer, 0, bufferLength);
|
||||
}
|
||||
|
||||
return messageDigest.digest();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Copyright (c) 2005-2012 springside.org.cn
|
||||
*/
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
public class Encodes {
|
||||
|
||||
private static final String DEFAULT_URL_ENCODING = "UTF-8";
|
||||
private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
|
||||
|
||||
/**
|
||||
* Hex编码.
|
||||
*/
|
||||
public static String encodeHex(byte[] input) {
|
||||
return new String(Hex.encodeHex(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex解码.
|
||||
*/
|
||||
public static byte[] decodeHex(String input) {
|
||||
try {
|
||||
return Hex.decodeHex(input.toCharArray());
|
||||
} catch (DecoderException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64编码.
|
||||
*/
|
||||
public static String encodeBase64(byte[] input) {
|
||||
return new String(Base64.encodeBase64(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64编码.
|
||||
*/
|
||||
public static String encodeBase64(String input) {
|
||||
try {
|
||||
return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
|
||||
// */
|
||||
// public static String encodeUrlSafeBase64(byte[] input) {
|
||||
// return Base64.encodeBase64URLSafe(input);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Base64解码.
|
||||
*/
|
||||
public static byte[] decodeBase64(String input) {
|
||||
return Base64.decodeBase64(input.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64解码.
|
||||
*/
|
||||
public static String decodeBase64String(String input) {
|
||||
try {
|
||||
return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base62编码。
|
||||
*/
|
||||
public static String encodeBase62(byte[] input) {
|
||||
char[] chars = new char[input.length];
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Html 转码.
|
||||
*/
|
||||
public static String escapeHtml(String html) {
|
||||
return StringEscapeUtils.escapeHtml4(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Html 解码.
|
||||
*/
|
||||
public static String unescapeHtml(String htmlEscaped) {
|
||||
return StringEscapeUtils.unescapeHtml4(htmlEscaped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml 转码.
|
||||
*/
|
||||
public static String escapeXml(String xml) {
|
||||
return StringEscapeUtils.escapeXml10(xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml 解码.
|
||||
*/
|
||||
public static String unescapeXml(String xmlEscaped) {
|
||||
return StringEscapeUtils.unescapeXml(xmlEscaped);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL 编码, Encode默认为UTF-8.
|
||||
*/
|
||||
public static String urlEncode(String part) {
|
||||
try {
|
||||
return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL 解码, Encode默认为UTF-8.
|
||||
*/
|
||||
public static String urlDecode(String part) {
|
||||
|
||||
try {
|
||||
return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* 关于异常的工具类.
|
||||
*/
|
||||
public class Exceptions {
|
||||
private static Logger logger = LoggerFactory.getLogger(Exceptions.class);
|
||||
|
||||
/**
|
||||
* 将CheckedException转换为UncheckedException.
|
||||
*/
|
||||
public static RuntimeException unchecked(Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
return (RuntimeException) e;
|
||||
} else {
|
||||
return new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将ErrorStack转化为String.
|
||||
*/
|
||||
public static String getStackTraceAsString(Throwable e) {
|
||||
if (e == null) {
|
||||
return "";
|
||||
}
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(stringWriter));
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断异常是否由某些底层的异常引起.
|
||||
*/
|
||||
public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
|
||||
Throwable cause = ex.getCause();
|
||||
while (cause != null) {
|
||||
for (Class<? extends Exception> causeClass : causeExceptionClasses) {
|
||||
if (causeClass.isInstance(cause)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
cause = cause.getCause();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在request中获取异常类
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static Throwable getThrowable(HttpServletRequest request) {
|
||||
Throwable ex = null;
|
||||
if (request.getAttribute("exception") != null) {
|
||||
ex = (Throwable) request.getAttribute("exception");
|
||||
} else if (request.getAttribute("javax.servlet.error.exception") != null) {
|
||||
ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.util.Map;
|
||||
|
||||
public class GBSignUtils {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(GBSignUtils.class);
|
||||
|
||||
public static String sign(Map<String, String> paramValues, String secret) {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String value : paramValues.values()) {
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
sb.append(value);
|
||||
}
|
||||
}
|
||||
logger.debug("需要签名的内容:{},密钥{}", sb.toString(), secret);
|
||||
byte[] md5Digest = HmacMD5Encrypt(sb.toString(), secret);
|
||||
String result = Encodes.encodeHex(md5Digest).toUpperCase();
|
||||
logger.debug("HmacSHA1的签名内容:{}", result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("数据签名出错", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 HMAC-MD5 签名方法对对encryptText进行签名
|
||||
*
|
||||
* @param encryptText
|
||||
* 被签名的字符串
|
||||
* @param encryptKey
|
||||
* 密钥
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static byte[] HmacMD5Encrypt(String encryptText, String encryptKey) throws Exception {
|
||||
byte[] data = encryptKey.getBytes("UTF-8");
|
||||
// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
|
||||
SecretKey secretKey = new SecretKeySpec(data, "HmacMD5");
|
||||
// 生成一个指定 Mac 算法 的 Mac 对象
|
||||
Mac mac = Mac.getInstance("HmacMD5");
|
||||
// 用给定密钥初始化 Mac 对象
|
||||
mac.init(secretKey);
|
||||
|
||||
byte[] text = encryptText.getBytes("UTF-8");
|
||||
// 完成 Mac 操作
|
||||
return mac.doFinal(text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
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.util.EntityUtils;
|
||||
|
||||
/**
|
||||
* @author 联联充电
|
||||
*/
|
||||
@Slf4j
|
||||
@SuppressWarnings(value = "unused")
|
||||
public class HttpRequestUtil {
|
||||
|
||||
|
||||
/**
|
||||
* httpClient--post请求--http
|
||||
*
|
||||
* @param url
|
||||
* @param json
|
||||
* @return
|
||||
*/
|
||||
public static String httpPost(String url, String json, String token) {
|
||||
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
//创建httpPost
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
|
||||
//设置Content-Type
|
||||
httpPost.setHeader("Content-Type", "application/json");
|
||||
httpPost.setHeader("Authorization", token);
|
||||
|
||||
//写入json数据
|
||||
httpPost.setEntity(new StringEntity(json));
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(50000)
|
||||
.setConnectionRequestTimeout(50000)
|
||||
.setSocketTimeout(50000)
|
||||
.build();
|
||||
httpPost.setConfig(requestConfig);
|
||||
|
||||
//发起请求,获取response对象
|
||||
response = httpClient.execute(httpPost);
|
||||
|
||||
//获取结果状态码
|
||||
int resultCode = response.getStatusLine().getStatusCode();
|
||||
if (resultCode == 200) {
|
||||
//获取返回数据实体对象
|
||||
HttpEntity entity = response.getEntity();
|
||||
|
||||
//转化为字符串
|
||||
String result = EntityUtils.toString(entity, "UTF-8");
|
||||
//封装统一的返回数据接收类
|
||||
//ResponseMsg responseMsg = (ResponseMsg) JSON.parse(result);
|
||||
return result;
|
||||
} else {
|
||||
log.info("http请求失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("http请求异常");
|
||||
} finally {
|
||||
try {
|
||||
if (httpClient != null) {
|
||||
httpClient.close();
|
||||
}
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import com.jsowell.common.constant.Constants;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 联联平台工具类
|
||||
*
|
||||
* @author JS-ZZA
|
||||
* @date 2023/5/6 14:22
|
||||
*/
|
||||
public class LianLianUtils {
|
||||
static final String ALGORITHM_MAC = "HmacMD5";
|
||||
|
||||
/** 密钥 **/
|
||||
static final String MAC_KEY = "TmsdVaFVTtjzZbLi";
|
||||
|
||||
|
||||
/**
|
||||
* HMAC加密
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encryptionHMAC(String source) throws Exception {
|
||||
SecretKey secretKey = new SecretKeySpec(MAC_KEY.getBytes("UTF-8"), ALGORITHM_MAC);
|
||||
Mac mac = Mac.getInstance(ALGORITHM_MAC);
|
||||
mac.init(secretKey);
|
||||
mac.update(source.getBytes("UTF-8"));
|
||||
return BytesUtil.binary(mac.doFinal(), 16).toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接参数
|
||||
* @param Data
|
||||
* @return
|
||||
*/
|
||||
public static String connectData(String Data){
|
||||
String timeStamp = DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSS);
|
||||
String number = "0001";
|
||||
return Constants.OPERATORID_LIANLIAN + Data + timeStamp + number;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.jsowell.common.util.lianlian;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
public class SignUtils {
|
||||
|
||||
private static String UTF_8 = "UTF-8";
|
||||
|
||||
/**
|
||||
* 使用<code>secret</code>对paramValues按以下算法进行签名: <br/>
|
||||
* uppercase(hex(sha1(secretkey1value1key2value2...secret))
|
||||
*
|
||||
* @param paramValues
|
||||
* 参数列表
|
||||
* @param secret
|
||||
* @return
|
||||
*/
|
||||
public static String sign(Map<String, String> paramValues, String secret) {
|
||||
return sign(paramValues, null, secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对paramValues进行签名,其中ignoreParamNames这些参数不参与签名
|
||||
*
|
||||
* @param paramValues
|
||||
* @param ignoreParamNames
|
||||
* @param secret
|
||||
* @return
|
||||
*/
|
||||
public static String sign(Map<String, String> paramValues, List<String> ignoreParamNames, String secret) {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<String> paramNames = new ArrayList<String>(paramValues.size());
|
||||
paramNames.addAll(paramValues.keySet());
|
||||
if (ignoreParamNames != null && ignoreParamNames.size() > 0) {
|
||||
for (String ignoreParamName : ignoreParamNames) {
|
||||
paramNames.remove(ignoreParamName);
|
||||
}
|
||||
}
|
||||
Collections.sort(paramNames);
|
||||
|
||||
sb.append(secret);
|
||||
for (String paramName : paramNames) {
|
||||
sb.append(paramName).append(paramValues.get(paramName));
|
||||
}
|
||||
sb.append(secret);
|
||||
System.out.println("原始的签名:" + sb.toString());
|
||||
byte[] sha1Digest = getSHA1Digest(sb.toString());
|
||||
System.out.println("sha-1的二进制码:" + String.valueOf(sha1Digest));
|
||||
return byte2hex(sha1Digest);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String utf8Encoding(String value, String sourceCharsetName) {
|
||||
try {
|
||||
return new String(value.getBytes(sourceCharsetName), UTF_8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getSHA1Digest(String data) throws IOException {
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
bytes = md.digest(data.getBytes(UTF_8));
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new IOException(gse.getMessage()) ;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// private static byte[] getMD5Digest(String data) throws IOException {
|
||||
// byte[] bytes = null;
|
||||
// try {
|
||||
// MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
// bytes = md.digest(data.getBytes(UTF_8));
|
||||
// } catch (GeneralSecurityException gse) {
|
||||
// throw new IOException(gse.getMessage());
|
||||
// }
|
||||
// return bytes;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 二进制转十六进制字符串
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
private static String byte2hex(byte[] bytes) {
|
||||
StringBuilder sign = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
String hex = Integer.toHexString(bytes[i] & 0xFF);
|
||||
if (hex.length() == 1) {
|
||||
sign.append("0");
|
||||
}
|
||||
sign.append(hex.toUpperCase());
|
||||
}
|
||||
System.out.println("最终的签名:" + sign);
|
||||
return sign.toString();
|
||||
}
|
||||
|
||||
public static String getUUID() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
return uuid.toString().toUpperCase();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.jsowell.pile.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 联联充电获取令牌
|
||||
*
|
||||
* @author JS-ZZA
|
||||
* @date 2023/5/9 13:54
|
||||
*/
|
||||
@Data
|
||||
public class LianLianGetTokenDTO {
|
||||
@JsonProperty(value = "OperatorID")
|
||||
private String operatorId;
|
||||
|
||||
@JsonProperty(value = "OperatorSecret")
|
||||
private String operatorSecret;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.jsowell.thirdparty.service;
|
||||
|
||||
import com.jsowell.pile.dto.LianLianGetTokenDTO;
|
||||
import com.jsowell.pile.dto.QueryEquipmentDTO;
|
||||
import com.jsowell.pile.dto.QueryStartChargeDTO;
|
||||
import com.jsowell.thirdparty.domain.StationStatsInfo;
|
||||
@@ -16,6 +17,12 @@ public interface LianLianService {
|
||||
*/
|
||||
void pushMerchantInfo(Long merchantId);
|
||||
|
||||
/**
|
||||
* 根据充电站id,推送充电站信息
|
||||
* @param stationId
|
||||
*/
|
||||
void pushStationInfo(Long stationId) throws Exception;
|
||||
|
||||
/**
|
||||
* 联联平台获取充电站信息
|
||||
* @param dto
|
||||
@@ -67,4 +74,6 @@ public interface LianLianService {
|
||||
* @return
|
||||
*/
|
||||
QueryStopChargeVO query_stop_charge(QueryStartChargeDTO dto);
|
||||
|
||||
String getToken(LianLianGetTokenDTO dto);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
package com.jsowell.thirdparty.service.impl;
|
||||
|
||||
import cn.hutool.core.util.PageUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.constant.Constants;
|
||||
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
|
||||
import com.jsowell.common.core.redis.RedisCache;
|
||||
import com.jsowell.common.enums.ykc.OrderStatusEnum;
|
||||
import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
|
||||
import com.jsowell.common.exception.BusinessException;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.PageUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.*;
|
||||
import com.jsowell.common.util.http.HttpUtils;
|
||||
import com.jsowell.common.util.lianlian.Cryptos;
|
||||
import com.jsowell.common.util.lianlian.Encodes;
|
||||
import com.jsowell.common.util.lianlian.GBSignUtils;
|
||||
import com.jsowell.common.util.lianlian.LianLianUtils;
|
||||
import com.jsowell.netty.command.ykc.StartChargingCommand;
|
||||
import com.jsowell.netty.command.ykc.StopChargingCommand;
|
||||
import com.jsowell.netty.service.yunkuaichong.YKCPushCommandService;
|
||||
import com.jsowell.pile.domain.*;
|
||||
import com.jsowell.pile.dto.LianLianGetTokenDTO;
|
||||
import com.jsowell.pile.dto.QueryEquipmentDTO;
|
||||
import com.jsowell.pile.dto.QueryStartChargeDTO;
|
||||
import com.jsowell.pile.dto.QueryStationInfoDTO;
|
||||
@@ -27,7 +35,6 @@ import com.jsowell.pile.service.IPileStationInfoService;
|
||||
import com.jsowell.pile.vo.base.ConnectorInfoVO;
|
||||
import com.jsowell.pile.vo.base.MerchantInfoVO;
|
||||
import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO;
|
||||
import com.jsowell.pile.vo.uniapp.SendMessageVO;
|
||||
import com.jsowell.pile.vo.web.PileConnectorInfoVO;
|
||||
import com.jsowell.pile.vo.web.PileModelInfoVO;
|
||||
import com.jsowell.thirdparty.domain.ConnectorChargeStatusInfo;
|
||||
@@ -47,9 +54,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@@ -82,13 +87,81 @@ public class LianLianServiceImpl implements LianLianService {
|
||||
MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(String.valueOf(merchantId));
|
||||
// 组装联联平台所需要的数据格式
|
||||
OperatorInfo operatorInfo = OperatorInfo.builder()
|
||||
.OperatorID(merchantInfo.getOrganizationCode()) // 组织机构代码
|
||||
.OperatorID(Constants.OPERATORID_LIANLIAN) // 组织机构代码
|
||||
.OperatorName(merchantInfo.getMerchantName()) // 机构全称
|
||||
.OperatorTel1(merchantInfo.getMerchantTel()) // 对接平台客服电话1
|
||||
.build();
|
||||
// 调用联联平台接口
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据站点id推送站点信息
|
||||
* @param stationId
|
||||
*/
|
||||
@Override
|
||||
public void pushStationInfo(Long stationId) throws Exception {
|
||||
// 通过id查询站点相关信息
|
||||
PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(stationId);
|
||||
// 组装联联平台所需要的数据格式
|
||||
StationInfo info = StationInfo.builder()
|
||||
.StationID(String.valueOf(stationId))
|
||||
.OperatorID(Constants.OPERATORID_LIANLIAN)
|
||||
.EquipmentOwnerID(Constants.OPERATORID_LIANLIAN)
|
||||
.StationName(pileStationInfo.getStationName())
|
||||
.IsAloneApply(Integer.valueOf(pileStationInfo.getAloneApply()))
|
||||
.IsPublicParkingLot(Integer.valueOf(pileStationInfo.getPublicParking()))
|
||||
.CountryCode(pileStationInfo.getCountryCode())
|
||||
.AreaCode(pileStationInfo.getAreaCode())
|
||||
.Address(pileStationInfo.getAddress())
|
||||
.ServiceTel(pileStationInfo.getServiceTel())
|
||||
.StationType(Integer.valueOf(pileStationInfo.getStationType()))
|
||||
.StationStatus(Integer.valueOf(pileStationInfo.getStationStatus()))
|
||||
.ParkNums(Integer.valueOf(pileStationInfo.getParkNums()))
|
||||
.StationLng(new BigDecimal(pileStationInfo.getStationLng()))
|
||||
.StationLat(new BigDecimal(pileStationInfo.getStationLat()))
|
||||
.Construction(Integer.valueOf(pileStationInfo.getConstruction()))
|
||||
.OpenAllDay(Integer.valueOf(pileStationInfo.getOpenAllDay()))
|
||||
// .MinElectricityPrice()
|
||||
// .ElectricityFee()
|
||||
// .ServiceFee()
|
||||
.ParkFree(Integer.valueOf(pileStationInfo.getParkFree()))
|
||||
// .ParkFee()
|
||||
.Payment(pileStationInfo.getPayment())
|
||||
.SupportOrder(Integer.valueOf(pileStationInfo.getSupportOrder()))
|
||||
// .equipmentInfos()
|
||||
// .ParkFeeType()
|
||||
.ToiletFlag(Integer.valueOf(pileStationInfo.getToiletFlag()))
|
||||
.StoreFlag(Integer.valueOf(pileStationInfo.getStoreFlag()))
|
||||
.RestaurantFlag(Integer.valueOf(pileStationInfo.getRestaurantFlag()))
|
||||
.LoungeFlag(Integer.valueOf(pileStationInfo.getLoungeFlag()))
|
||||
.CanopyFlag(Integer.valueOf(pileStationInfo.getCanopyFlag()))
|
||||
.PrinterFlag(Integer.valueOf(pileStationInfo.getPrinterFlag()))
|
||||
.BarrierFlag(Integer.valueOf(pileStationInfo.getBarrierFlag()))
|
||||
.ParkingLockFlag(Integer.valueOf(pileStationInfo.getParkingLockFlag()))
|
||||
|
||||
.build();
|
||||
|
||||
List<EquipmentInfo> pileList = getPileList(pileStationInfo);
|
||||
if (CollectionUtils.isNotEmpty(pileList)) {
|
||||
info.setEquipmentInfos(pileList); // 充电设备信息列表
|
||||
}
|
||||
|
||||
// 调用联联平台接口
|
||||
String url = "http://dataexchange.evchargeonline.com:81/shevcs/v1/" + "notification_stationInfo";
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
// Map<String, Object> map = new HashMap<>();
|
||||
jsonObject.put("StationInfo", info);
|
||||
String s = HttpUtils.sendPost(url, jsonObject.toJSONString());
|
||||
|
||||
System.out.println(s);
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,8 +185,8 @@ public class LianLianServiceImpl implements LianLianService {
|
||||
for (PileStationInfo pileStationInfo : pageInfo.getList()) {
|
||||
StationInfo stationInfo = new StationInfo();
|
||||
stationInfo.setStationID(String.valueOf(pileStationInfo.getId()));
|
||||
MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(String.valueOf(pileStationInfo.getMerchantId()));
|
||||
stationInfo.setOperatorID(merchantInfo.getOrganizationCode()); // 组织机构代码
|
||||
// MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(String.valueOf(pileStationInfo.getMerchantId()));
|
||||
stationInfo.setOperatorID(Constants.OPERATORID_LIANLIAN); // 组织机构代码
|
||||
stationInfo.setEquipmentOwnerID(String.valueOf(pileStationInfo.getMerchantId()));
|
||||
stationInfo.setStationName(pileStationInfo.getStationName());
|
||||
stationInfo.setIsAloneApply(Integer.valueOf(pileStationInfo.getAloneApply()));
|
||||
@@ -481,6 +554,60 @@ public class LianLianServiceImpl implements LianLianService {
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取令牌
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getToken(LianLianGetTokenDTO dto) {
|
||||
String operatorId = dto.getOperatorId();
|
||||
String operatorSecret = dto.getOperatorSecret();
|
||||
String token = "";
|
||||
try {
|
||||
//测试用请求地址
|
||||
String requestUrl = "http://testdataexchange.evchargeonline.com:82/shevcs/v1/query_token";
|
||||
|
||||
//请求data
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("OperatorID", operatorId);
|
||||
data.put("OperatorSecret", operatorSecret);
|
||||
String dataJson = JSONUtil.toJsonStr(data);
|
||||
|
||||
//加密
|
||||
byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
|
||||
operatorSecret.getBytes(), operatorSecret.getBytes());
|
||||
String strData = Encodes.encodeBase64(encryptText);
|
||||
|
||||
Map<String, String> request = new LinkedHashMap<>();
|
||||
request.put("OperatorID", operatorId);
|
||||
request.put("Data", strData);
|
||||
request.put("TimeStamp", System.currentTimeMillis() + "");
|
||||
request.put("Seq", "0001");
|
||||
|
||||
//生成签名
|
||||
String sig = GBSignUtils.sign(request, operatorSecret);
|
||||
request.put("Sig", sig);
|
||||
|
||||
String tokenRequest = JSONUtil.toJsonStr(request);
|
||||
|
||||
String response = HttpUtil.post(requestUrl, tokenRequest);
|
||||
LianLianResultVO result = JSON.parseObject(response, LianLianResultVO.class);
|
||||
|
||||
if (result.getRet() == 0) {
|
||||
//解密data
|
||||
byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64((String) result.getData()),
|
||||
operatorSecret.getBytes(), operatorSecret.getBytes());
|
||||
String dataStr = new String(plainText, "UTF-8");
|
||||
Map<String, String> resultMap = (Map<String, String>) JSON.parse(dataStr);
|
||||
token = resultMap.get("AccessToken");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return token;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
// TODO 推送停止充电结果 notification_stop_charge_result
|
||||
|
||||
// TODO 推送充电订单信息 notification_charge_order_info
|
||||
|
||||
43
jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/vo/LianLianResultVO.java
vendored
Normal file
43
jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/vo/LianLianResultVO.java
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.jsowell.thirdparty.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 联联平台接口返回对象
|
||||
*
|
||||
* @author JS-ZZA
|
||||
* @date 2023/5/10 8:36
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class LianLianResultVO {
|
||||
/**
|
||||
* 系统错误码
|
||||
*/
|
||||
@JsonProperty("Ret")
|
||||
int ret = 0;
|
||||
|
||||
/**
|
||||
* 返回提示信息
|
||||
*/
|
||||
@JsonProperty("Msg")
|
||||
String msg = "";
|
||||
|
||||
/**
|
||||
* 返回结果
|
||||
*/
|
||||
@JsonProperty("Data")
|
||||
Object data;
|
||||
|
||||
/**
|
||||
* 签名
|
||||
*/
|
||||
@JsonProperty("Sig")
|
||||
String sig;
|
||||
}
|
||||
Reference in New Issue
Block a user