新增对 SIM 卡商的 HTTP 状态查询和流量查询接口
This commit is contained in:
parent
aa0ef8625d
commit
6d6a400dca
@ -0,0 +1,20 @@
|
||||
package com.imdroid.sideslope.service;
|
||||
|
||||
import com.imdroid.sideslope.sal.Device;
|
||||
import com.imdroid.sideslope.simcard.*;
|
||||
|
||||
public interface SimCardQueryService {
|
||||
|
||||
// 查询卡基本信息
|
||||
BaseResponse<CardInfoData> queryCardInfo(Device device);
|
||||
|
||||
// 查询卡状态
|
||||
BaseResponse<CardStatusData> queryCardStatus(Device device);
|
||||
|
||||
// 查询流量信息
|
||||
BaseResponse<GprsData> queryGprs(Device device);
|
||||
|
||||
// 查询卡详细信息
|
||||
BaseResponse<CardDetailData> queryCardDetail(Device device);
|
||||
|
||||
}
|
||||
@ -0,0 +1,179 @@
|
||||
package com.imdroid.sideslope.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.imdroid.secapi.dto.GnssStatusJoin;
|
||||
import com.imdroid.secapi.dto.SimCard;
|
||||
import com.imdroid.secapi.dto.SimCardsMapper;
|
||||
import com.imdroid.sideslope.sal.Device;
|
||||
import com.imdroid.sideslope.sal.DeviceService;
|
||||
import com.imdroid.sideslope.simcard.*;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class SimCardQueryServiceImpl implements SimCardQueryService{
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private static final String BASE_URL = "http://120.78.169.220:8089";
|
||||
private static final String USERNAME = "gzyzdz";
|
||||
private static final String KEY = "632629d1269a202c9d49a574623e4e4c";
|
||||
|
||||
@Resource(name = "local")
|
||||
private DeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
SimCardsMapper simCardsMapper;
|
||||
|
||||
@Override
|
||||
public BaseResponse<CardInfoData> queryCardInfo(Device device) {
|
||||
return executeQuery(device, "/api/Service/Cardinfo", CardInfoData.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseResponse<CardStatusData> queryCardStatus(Device device) {
|
||||
return executeQuery(device, "/api/Service/QueryCardStatus", CardStatusData.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseResponse<GprsData> queryGprs(Device device) {
|
||||
return executeQuery(device, "/api/Service/QueryGprs", GprsData.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseResponse<CardDetailData> queryCardDetail(Device device) {
|
||||
return executeQuery(device, "/api/Service/QueryCard", CardDetailData.class);
|
||||
}
|
||||
|
||||
private <T> BaseResponse<T> executeQuery(Device device, String path, Class<T> responseType) {
|
||||
try {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("username", USERNAME);
|
||||
params.put("key", KEY);
|
||||
params.put("card", device.getIccid());
|
||||
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
|
||||
|
||||
String signature = calculateSignature(params);
|
||||
params.put("signature", signature);
|
||||
|
||||
logger.info("Request params: {}", params);
|
||||
String response = sendHttpPost(path, params);
|
||||
logger.info("查询响应: 设备={}, ICCID={}, 响应={}",
|
||||
device.getDeviceId(), device.getIccid(), response);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
|
||||
|
||||
// 特殊处理CardStatus的数组响应
|
||||
if (responseType == CardStatusData.class) {
|
||||
JsonNode root = mapper.readTree(response);
|
||||
if (root.get("Status").asInt() == 1 && root.get("Data").isArray()) {
|
||||
CardStatusData statusData = new CardStatusData();
|
||||
statusData.setStatusCode(root.get("Data").get(0).asInt());
|
||||
statusData.setStatusDesc(root.get("Data").get(1).asText());
|
||||
BaseResponse<CardStatusData> baseResponse = new BaseResponse<>();
|
||||
baseResponse.setStatus(1);
|
||||
baseResponse.setMessage("Success");
|
||||
baseResponse.setData(statusData);
|
||||
return (BaseResponse<T>) baseResponse;
|
||||
}
|
||||
}
|
||||
|
||||
JavaType type = mapper.getTypeFactory().constructParametricType(BaseResponse.class, responseType);
|
||||
return mapper.readValue(response, type);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("查询失败: 设备={}, 错误={}", device.getDeviceId(), e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String calculateSignature(Map<String, String> params) {
|
||||
try {
|
||||
List<String> paramList = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
paramList.add(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
Collections.sort(paramList);
|
||||
|
||||
String paramString = String.join("&", paramList);
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] digest = md.digest(paramString.getBytes());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : digest) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
String signature = sb.toString();
|
||||
logger.debug("Signature: {}", signature);
|
||||
return signature;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("签名计算失败: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String sendHttpPost(String path, Map<String, String> params) throws Exception {
|
||||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||
HttpPost httpPost = new HttpPost(BASE_URL + path);
|
||||
|
||||
List<BasicNameValuePair> pairs = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
|
||||
httpPost.setEntity(new UrlEncodedFormEntity(pairs));
|
||||
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
|
||||
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
|
||||
return EntityUtils.toString(response.getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasValidIccid(Device device) {
|
||||
return device.getIccid() != null && !device.getIccid().trim().isEmpty();
|
||||
}
|
||||
|
||||
public SimCard CreateOrUpdateSimCard(Device device) {
|
||||
SimCard simCard = simCardsMapper.queryByDeviceId(device.getDeviceId());
|
||||
if (simCard == null) {
|
||||
simCard = createNewSimCard(device);
|
||||
}
|
||||
return simCard;
|
||||
}
|
||||
|
||||
public SimCard createNewSimCard(Device device) {
|
||||
SimCard newCard = new SimCard();
|
||||
newCard.setDeviceid(device.getDeviceId());
|
||||
newCard.setUpdatetime(new Date());
|
||||
newCard.setIccid(device.getIccid());
|
||||
newCard.setStatus(-1);
|
||||
newCard.setMsisdn("");
|
||||
newCard.setRemaining(BigDecimal.ZERO);
|
||||
newCard.setUsed(BigDecimal.ZERO);
|
||||
newCard.setTotal(BigDecimal.ZERO);
|
||||
|
||||
simCardsMapper.insert(newCard);
|
||||
return newCard;
|
||||
}
|
||||
|
||||
public boolean isValidResponse(BaseResponse<?> response) {
|
||||
return response != null && response.getStatus() == 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.imdroid.sideslope.simcard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BaseResponse<T> {
|
||||
private Integer status;
|
||||
private String message;
|
||||
private T data;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.imdroid.sideslope.simcard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CardDetailData {
|
||||
private Integer operatortype;
|
||||
private String activetime;
|
||||
private String starttime;
|
||||
private String stoptime;
|
||||
private String silentdate;
|
||||
private Integer status;
|
||||
private String msisdn;
|
||||
private String iccid;
|
||||
private String imsi;
|
||||
private Integer packageid;
|
||||
private String packagename;
|
||||
private String net;
|
||||
|
||||
private GprsInfo gprs;
|
||||
private ApnInfo apn;
|
||||
|
||||
@Data
|
||||
public static class GprsInfo {
|
||||
private Double total;
|
||||
private Double used;
|
||||
private Double left;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ApnInfo {
|
||||
private String apnid;
|
||||
private String status;
|
||||
private String ip;
|
||||
private String rat;
|
||||
private String onoffstatus;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.imdroid.sideslope.simcard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CardInfoData {
|
||||
private String imsi;
|
||||
private String msisdn;
|
||||
private String iccid;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.imdroid.sideslope.simcard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class CardStatusData {
|
||||
private Integer statusCode;
|
||||
private String statusDesc;
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.imdroid.sideslope.simcard;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class GprsData {
|
||||
private Integer operatortype;
|
||||
private List<GprsUsage> gps;
|
||||
|
||||
@Data
|
||||
public static class GprsUsage {
|
||||
private Double left;
|
||||
private Double total;
|
||||
private Double used;
|
||||
}
|
||||
|
||||
// 返回数据格式
|
||||
// {
|
||||
// "Status": 1,
|
||||
// "Message": "Success",
|
||||
// "Data": {
|
||||
// "operatortype": 1,
|
||||
// "GPS": [
|
||||
// {
|
||||
// "Left": "2023",
|
||||
// "Total": "2.0",
|
||||
// "Used": "25"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
|
||||
public GprsUsage getFirstGprsUsage() {
|
||||
if (gps != null && !gps.isEmpty()) {
|
||||
return gps.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user