4、IRS 接口调用
IRS 接口调用
特别说明:
- 1、在组件超市中目前存在两种方式调用,组件详情页中展示的调用地址为:“https://interface.zjzwfw.gov.cn/gateway/component/routing/agent.htm” 时参考《调用方式一》进行对接。
- 2、组件超市页面展示的调用地址类似:“https://bcdsg.zj.gov.cn:8443/restapi/prod/*”地址时,采用《调用方式二》进行对接。
快速调用示例
public static void main(String[] args) {
String accessKey = "你的 accessKey";
String secretKey = "你的 secretKey ";
String urlStr = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020240523000016/proxy/eccbc87e4b5ce2fe28308fd9f2a7baf3/c51ce410c124a10e0db5e4b97fc2af39/addrdata/associate/api/search";
UrlBuilder builder = UrlBuilder.of(urlStr)
.addQuery("query", "杭州中泰中心小学")
.addQuery("adcode", "330000")
.addQuery("ack", "6ba46de613594b4b88e93613e36a3fd8");
long timeMillis = System.currentTimeMillis();
Map<String, String> headers = HmacAuthUtil.generateHeader(builder.build(), HttpMethod.GET.name(), accessKey, secretKey);
HttpResponse<String> response = Unirest.get(builder.build())
.headers(headers)
.asString();
System.out.println(response.getBody());
System.out.println(timeMillis);
System.out.println(Md5Utils.md5(accessKey + secretKey + timeMillis));
}业务中的示例
1、添加Maven依赖
<!-- https://mvnrepository.com/artifact/com.konghq/unirest-java -->
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.14.5</version>
</dependency>2、公共工具类
- HmacAuthUtil
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* 仅适用于IRS请求信息加密
*/
@Slf4j
public class HmacAuthUtil {
public static void main(String[] args) {
String url="http://59.202.53.51:9080/restapi/prod/IC33000020220124000009/ip";
String ak = "test11";
String sk = "test333";
String method="GET";
Map<String, String> header = HmacAuthUtil.generateHeader(url, method, ak, sk);
Iterator<String> its = header.keySet().iterator();
while(its.hasNext()){
String next = its.next();
System.out.println(next+":"+header.get(next));
}
}
/**
* 构造请求 header
* @param urlStr 请求url,全路径格式,比如:https://bcdsg.zj.gov.cn/api/p/v1/user.get
* @param requestMethod 请求方法,大写格式,如:GET, POST
* @param accessKey 应用的 AK
* @param secretKey 应用的 SK
* @return
*/
public static Map<String, String> generateHeader(String urlStr, String requestMethod, String accessKey, String secretKey) {
log.info("params,urlStr={},requestMethod={},accessKey={},secretKey={}",urlStr,requestMethod,accessKey,secretKey);
Map<String, String> header = new HashMap<>();
try {
DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = dateFormat.format(new Date());
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
String canonicalQueryString = getCanonicalQueryString(uri.getQuery());
String message = requestMethod.toUpperCase() + "\n" + uri.getPath() + "\n" + canonicalQueryString + "\n" + accessKey + "\n" + date + "\n";
Mac hasher = Mac.getInstance("HmacSHA256");
hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
byte[] hash = hasher.doFinal(message.getBytes());
// to lowercase hexits
DatatypeConverter.printHexBinary(hash);
// to base64
String sign = DatatypeConverter.printBase64Binary(hash);
header.put("X-BG-HMAC-SIGNATURE", sign);
header.put("X-BG-HMAC-ALGORITHM", "hmac-sha256");
header.put("X-BG-HMAC-ACCESS-KEY", accessKey);
header.put("X-BG-DATE-TIME", date);
} catch (Exception e) {
log.error("generate error",e);
throw new RuntimeException("generate header error");
}
log.info("header info,{}",header);
return header;
}
private static String getCanonicalQueryString(String query) {
if (query == null || query.trim().length() == 0) {
return "";
}
List<Pair<String, String>> queryParamList = new ArrayList<>();
String[] params = query.split("&");
for (String param : params) {
int eqIndex = param.indexOf("=");
String key = param.substring(0, eqIndex);
String value = param.substring(eqIndex+1);
Pair<String, String> pair = new Pair<String, String>(key,value);
queryParamList.add(pair);
}
List<Pair<String, String>> sortedParamList = queryParamList.stream().sorted(Comparator.comparing(param -> param.getKey() + "=" + Optional.ofNullable(param.getValue()).orElse(""))).collect(Collectors.toList());
List<Pair<String, String>> encodeParamList = new ArrayList<>();
sortedParamList.stream().forEach(param -> {
try {
String key = URLEncoder.encode(param.getKey(), "utf-8");
String value = URLEncoder.encode(Optional.ofNullable(param.getValue()).orElse(""), "utf-8")
.replaceAll("\\%2B","%20")
.replaceAll("\\+","%20")
.replaceAll("\\%21","!")
.replaceAll("\\%27","'")
.replaceAll("\\%28","(")
.replaceAll("\\%29",")")
.replaceAll("\\%7E","~")
.replaceAll("\\%25","%")
;
encodeParamList.add(new Pair<>(key, value));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("encoding error");
}
});
StringBuilder queryParamString = new StringBuilder(64);
for (Pair<String, String> encodeParam : encodeParamList) {
queryParamString.append(encodeParam.getKey()).append("=").append(Optional.ofNullable(encodeParam.getValue()).orElse(""));
queryParamString.append("&");
}
return queryParamString.substring(0, queryParamString.length() - 1);
}
}
- Md5Utils
import lombok.SneakyThrows;
import java.security.MessageDigest;
/**
* 仅适用于IRS请求信息加密
*/
public class Md5Utils {
/**
* Md 5 string.
*
* @param src the src
* @param charset the charset
* @return the string
*/
@SneakyThrows
private static String md5(final String src, final String charset) {
MessageDigest md5;
StringBuilder hexValue = new StringBuilder(32);
md5 = MessageDigest.getInstance("MD5");
byte[] byteArray;
byteArray = src.getBytes(charset);
byte[] md5Bytes = md5.digest(byteArray);
for (byte md5Byte : md5Bytes) {
int val = ((int) md5Byte) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
/**
* Md 5 string.
*
* @param src the src
* @return the string
*/
public static String md5(final String src) {
return md5(src, "UTF-8");
}
}
IRS 组件,IRSComponentJobHandler 示例
import cn.hutool.core.net.url.UrlBuilder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tianyin.evaluation.admin.bmp.service.ISjZxxxXxjbsjlbService;
import com.tianyin.evaluation.admin.entity.bmp.SjZxxxXxjbsjlbEntity;
import com.tianyin.evaluation.job.util.HmacAuthUtil;
import com.tianyin.evaluation.job.util.Md5Utils;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.spring.boot.annotation.XxlJobCron;
import kong.unirest.HttpMethod;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* IRS 组件调用
* 特别说明:
* 1、在组件超市中目前存在两种方式调用,组件详情页中展示的调用地址为:“https://interface.zjzwfw.gov.cn/gateway/component/routing/agent.htm” 时参考《调用方式一》进行对接。
* 2、组件超市页面展示的调用地址类似:“https://bcdsg.zj.gov.cn:8443/restapi/prod/*”地址时,采用《调用方式二》进行对接。
*/
@Component
public class IRSComponentJobHandler {
private final static String GATEWAY = "https://interface.zjzwfw.gov.cn/gateway/component/routing/agent.htm";
@Autowired
private ISjZxxxXxjbsjlbService sjZxxxXxjbsjlbService;
/**
* IRS 配置
*/
@Value("${datasync.irs.geo.secret-key:}")
private String secretKey;
@Value("${datasync.irs.geo.access-key:}")
private String accessKey;
@Value("${datasync.irs.geo.adcode:330100}")
private String adcode;
@Value("${datasync.irs.geo.call-type:2}")
private int callType;
/**
* 1、空间地址服务组件
*/
@XxlJob("addrJobHandler")
@XxlJobCron(cron = "0 0 2 * * ?", desc = "空间地址服务组件", author = "wandl", selfStarting = true)
public ReturnT<String> addrJobHandler() throws Exception {
// 政务外网地址: https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020240523000016/proxy/eccbc87e4b5ce2fe28308fd9f2a7baf3/c51ce410c124a10e0db5e4b97fc2af39/addrdata/associate/api/search
// 互联网地址: https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020240523000016/proxy/eccbc87e4b5ce2fe28308fd9f2a7baf3/c51ce410c124a10e0db5e4b97fc2af39/addrdata/associate/api/search
List<SjZxxxXxjbsjlbEntity> schoolList = sjZxxxXxjbsjlbService.list(new LambdaQueryWrapper<SjZxxxXxjbsjlbEntity>()
.select(SjZxxxXxjbsjlbEntity::getXxbsm, SjZxxxXxjbsjlbEntity::getXxdm, SjZxxxXxjbsjlbEntity::getXxmc, SjZxxxXxjbsjlbEntity::getXxbxlxm)
.eq(SjZxxxXxjbsjlbEntity::getIsDelete, "0")
.isNotNull(SjZxxxXxjbsjlbEntity::getXxbsm));
if (CollectionUtils.isEmpty(schoolList)) {
XxlJobHelper.log("业务中台学校列表为空,无需执行IRS组件调用任务.");
return ReturnT.SUCCESS;
}
for (SjZxxxXxjbsjlbEntity schoolEntity : schoolList) {
/*
* zjgxfwxt-interface-code 是 string 接口请求唯一标识
* zjgxfwxt-access-key 是 string 应用访问授权码(AK)
* zjgxfwxt-sign 是 string 认证签名,签名规则:MD5(AK+SK+时间毫秒值),其签名值小写,MD5工具类详细信息详见附件(如何获取AK/SK,参考常见问题)
* zjgxfwxt-time 是 string 时间毫秒值(示例:1632643914516)
*/
long timeMillis = System.currentTimeMillis();
if(callType == 1){
HttpResponse<String> response = Unirest.get(GATEWAY)
// 请求头必须包含zjgxfwxt-interface-code、zjgxfwxt-time、zjgxfwxt-access-key、zjgxfwxt-sign
.header("zjgxfwxt-interface-code", "Z33000020240523000006")
.header("zjgxfwxt-access-key", accessKey)
.header("zjgxfwxt-sign", Md5Utils.md5(accessKey + secretKey + timeMillis))
.header("zjgxfwxt-time", String.valueOf(timeMillis))
.queryString("query", schoolEntity.getXxmc())
.queryString("adcode", adcode)
.queryString("ack", "6ba46de613594b4b88e93613e36a3fd8")
.asString();
XxlJobHelper.log("学校标识码: {},空间地址服务组件调用返回结果:{}", schoolEntity.getXxbsm(), response.getBody());
} else if(callType == 2){
String urlStr = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020240523000016/proxy/eccbc87e4b5ce2fe28308fd9f2a7baf3/c51ce410c124a10e0db5e4b97fc2af39/addrdata/associate/api/search";
UrlBuilder builder = UrlBuilder.of(urlStr)
.addQuery("query", schoolEntity.getXxmc())
.addQuery("adcode", adcode)
.addQuery("ack", "6ba46de613594b4b88e93613e36a3fd8");
Map<String, String> headers = HmacAuthUtil.generateHeader(builder.build(), HttpMethod.GET.name(), accessKey, secretKey);
HttpResponse<String> response = Unirest.get(builder.build())
.headers(headers)
.asString();
XxlJobHelper.log("学校标识码: {},空间地址服务组件调用返回结果:{}", schoolEntity.getXxbsm(), response.getBody());
}
TimeUnit.SECONDS.sleep(2);
}
return ReturnT.SUCCESS;
}
}作者:杭州天音 创建时间:2025-05-15 18:09
最后编辑:杭州天音 更新时间:2025-08-20 19:36
最后编辑:杭州天音 更新时间:2025-08-20 19:36