全国中小企业融资综合信用服务平台-省级节点数据接口规范-河南省营商环境和社会信用建设中心
开始之前先说一点题外话,几年前曾经看过一个视频,其中一个观点大概就是程序员是一个反传统的群体,其他群体掌握了某个技术,一般都是当做内部商业机密,而程序员则不一样,喜欢开源,尤其 GPL 协议的开源,不仅自己毫无保留的开源,还要求使用他的软件也得开源,也正是这种开源造就了互联网的蓬勃发展。我目前所在公司因为是做金融相关的公司,国家出于某些原因,要求要上报相关的数据到省平台,而省平台的技术采用的是 webservice,和我们目前习惯的 http 接口不太一样,所以前一段时间在写这个的时候走了不少弯路,而网上也没有参考资料,所以决定把相关的核心代码公布出来,供需要的同学参考。需要说明的是:这是我们河南省的系统相关接口,不知道外省是否一致,省平台给的接口文档名是:全国中小企业融资综合信用服务平台省级节点数据接口规范V5.3.pdf,首页写的是:全国中小企业融资综合信用服务平台省级节点数据接口规范,国家公共信用信息中心,河南省营商环境和社会信用建设中心,2024年7月
1. jar 包引入
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>4.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>4.0.5</version>
</dependency>
2. 上报工具类,其中:queryData 方法是用来查询,sendData 方法用来上报数据
package cn.bridgeli.demo;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.PublicKey;
@Slf4j
public class XyhnUtil {
private static String pubKey;
private static String queryPubKey;
private static PublicKey reportPublicKey;
// private static XyhnConfig xyhnConfig = SpringUtils.getBean(XyhnConfig.class);
private static XyhnConfig xyhnConfig = null;
/**
* 授权查询省平台接口
*
* @param method 要调取的方法名
* @param object 查询方法的参数(不包含:publicKey、appKey)
* @return 省平台解密后的数据
*/
public static String queryData(String method, JSONObject object) {
//1、组装报文
if (StringUtils.isEmpty(queryPubKey)) {
queryPubKey = convertFileToBase64(xyhnConfig.getQueryPubKeyPath());
}
object.put("publicKey", queryPubKey);
object.put("appKey", xyhnConfig.getQueryAppKey());
//2、发送报文
String jsonRes = callInterface("query", method, object.toJSONString());
//3、解密返回数据
JSONObject json = JSONObject.parseObject(jsonRes);
Boolean success = json.getBoolean("success");
if ("uploadLicense".equals(method)) {
if (null == success || !success) {
return jsonRes;
}
} else if ("cancelLicense".equals(method)) {
if (null != success && success) {
return jsonRes;
}
}
BigInteger d = new BigInteger(xyhnConfig.getQueryPriKey(), 16);
BCECPrivateKey bcecPrivateKey = GMUtil.getPrivatekeyFromD(d);
String key0 = json.getString("key");
String data = json.getString("data");
String signatureData = json.getString("signatureData");
byte[] decode = Hex.decode(key0);
// sm2解密
byte[] bytes1 = GMUtil.sm2Decrypt(decode, bcecPrivateKey);
// sm4解密
String content = GMUtil.sm4Decrypt(new String(bytes1), data);
log.info("content: " + content);
// 4、验签
File file = base64ToFileEx(json.getString("pubKey"));
PublicKey publicKey = GMUtil.getPublickeyFromX509File(file);
byte[] signatureData1 = Hex.decode(signatureData);
boolean verifyRes = GMUtil.verifySm3WithSm2(content.getBytes(), xyhnConfig.getUserId().getBytes(), signatureData1, publicKey);
log.info("method 验签结果:" + verifyRes);
if (!verifyRes) {
return null;
}
return content;
}
private static PublicKey getPublicKey() {
//1、组装报文
if (StringUtils.isEmpty(pubKey)) {
pubKey = convertFileToBase64(xyhnConfig.getPubKeyPath());
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", xyhnConfig.getAppKey());
JSONObject object = new JSONObject();
object.put("requestData", jsonObject);
object.put("publicKey", pubKey);
//2、发送报文
String jsonRes = callInterface("report", "getPublicKey", object.toJSONString());
//3、解密返回数据
JSONObject json = JSONObject.parseObject(jsonRes);
BigInteger d = new BigInteger(xyhnConfig.getPriKey(), 16);
BCECPrivateKey bcecPrivateKey = GMUtil.getPrivatekeyFromD(d);
String key0 = json.getString("key");
String data = json.getString("data");
String signatureData = json.getString("signatureData");
byte[] decode = Hex.decode(key0);
// sm2解密
byte[] bytes1 = GMUtil.sm2Decrypt(decode, bcecPrivateKey);
// sm4解密
String returnData = GMUtil.sm4Decrypt(new String(bytes1), data);
log.info("returnData:" + returnData);
// 4、验签
File file = base64ToFileEx(returnData);
PublicKey publicKey = GMUtil.getPublickeyFromX509File(file);
byte[] signatureData1 = Hex.decode(signatureData);
boolean verifyRes = GMUtil.verifySm3WithSm2(returnData.getBytes(), xyhnConfig.getUserId().getBytes(), signatureData1, publicKey);
log.info("getPublicKey 接口验签结果:" + verifyRes);
if (!verifyRes) {
return null;
}
return publicKey;
}
public static String sendData(String jsonStr, String method) {
log.info("调用省平台方法名:" + method + ",参数:" + jsonStr);
try {
if (StringUtils.isEmpty(pubKey)) { // 解析公钥
pubKey = convertFileToBase64(xyhnConfig.getPubKeyPath());
}
if (reportPublicKey == null) { //请求接口,获取公钥
reportPublicKey = getPublicKey();
}
// 1、摘要签名 sm2withsm3
byte[] msg = jsonStr.getBytes(CharEncoding.ISO_8859_1);
byte[] userIdBytes = xyhnConfig.getUserId().getBytes();
BigInteger d = new BigInteger(xyhnConfig.getPriKey(), 16);
BCECPrivateKey bcecPrivateKey = GMUtil.getPrivatekeyFromD(d);
byte[] sig = GMUtil.signSm3WithSm2(msg, userIdBytes, bcecPrivateKey);
String signature = Hex.toHexString(sig);
// 2、sm4加密数据报文
String key1 = RandomUtil.randomString(16);
String jsonobj = GMUtil.sm4Encrypt(key1, jsonStr);
//3、sm2加密16位随机码key
byte[] datamsg = GMUtil.sm2Encrypt(key1.getBytes(), reportPublicKey);
String s = Hex.toHexString(datamsg);
//4、组装并发送报文
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("requestData", jsonobj); // sm4加密的数据集
jsonObject2.put("key", s); // sm2加密的16位随机码
jsonObject2.put("signatureData", signature); // 签名
jsonObject2.put("publicKey", pubKey); // 我的公钥
jsonObject2.put("appKey", xyhnConfig.getAppKey()); // 数据授权的key
String setFPRes = callInterface("report", method, jsonObject2.toJSONString());
return setFPRes;
} catch (Exception ex) {
log.error("请求省平台接口异常", ex);
return null;
}
}
/**
* 请求接口
*
* @param type,report 回传数据,query 查询
* @param method
* @param json
* @return
*/
private static String callInterface(String type, String method, String json) {
log.info("调用省平台类型:" + type + ",接口:" + method + ",参数:" + json);
Client client = null;
QName name = null;
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
String result = null;
try {
if ("report".equals(type)) {
client = dcf.createClient(xyhnConfig.getWsAddr());
name = new QName(xyhnConfig.getNamespaceURI(), method);
} else if ("query".equals(type)) {
client = dcf.createClient(xyhnConfig.getQueryWsAddr());
name = new QName(xyhnConfig.getQueryNamespaceURI(), method);
}
Object[] objects = client.invoke(name, json);
result = objects[0].toString();
} catch (Exception e) {
log.error("调用省平台接口报错", e);
} finally {
if (client != null) {
try {
client.close();
} catch (Exception e) {
log.error("关闭Client资源时发生异常", e);
}
}
}
log.info("调用省平台类型:" + type + ",接口:" + method + ",返回值:" + result);
return result;
}
private static String convertFileToBase64(String imgPath) {
byte[] data = null;
// 读取图片字节数组
try (InputStream in = new FileInputStream(imgPath);) {
data = new byte[in.available()];
in.read(data);
} catch (IOException e) {
log.error("IOException", e);
}
// 对字节数组进行Base64编码,得到Base64编码的字符串
String base64Str = java.util.Base64.getEncoder().encodeToString(data);
return base64Str;
}
private static File base64ToFileEx(String base64) {
if (StringUtils.isBlank(base64)) {
return null;
}
byte[] buff = Base64.decode(base64);
File file = null;
FileOutputStream fout = null;
try {
file = File.createTempFile("tmp", null);
fout = new FileOutputStream(file);
fout.write(buff);
file.deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return file;
}
}
3. 用到的工具类
package cn.bridgeli.demo;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.spec.SM2ParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
@Slf4j
public class GMUtil {
private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
private static ECDomainParameters ecDomainParameters;
private static ECParameterSpec ecParameterSpec;
public static byte[] signSm3WithSm2(byte[] msg, byte[] userId, PrivateKey privateKey) {
return rsAsn1ToPlainByteArray(signSm3WithSm2Asn1Rs(msg, userId, privateKey));
}
public static byte[] signSm3WithSm2Asn1Rs(byte[] msg, byte[] userId, PrivateKey privateKey) {
try {
SM2ParameterSpec parameterSpec = new SM2ParameterSpec(userId);
Signature signer = Signature.getInstance("SM3withSM2", "BC");
signer.setParameter(parameterSpec);
signer.initSign(privateKey, new SecureRandom());
signer.update(msg, 0, msg.length);
byte[] sig = signer.sign();
return sig;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static boolean verifySm3WithSm2(byte[] msg, byte[] userId, byte[] rs, PublicKey publicKey) {
return verifySm3WithSm2Asn1Rs(msg, userId, rsPlainByteArrayToAsn1(rs), publicKey);
}
public static boolean verifySm3WithSm2Asn1Rs(byte[] msg, byte[] userId, byte[] rs, PublicKey publicKey) {
try {
SM2ParameterSpec parameterSpec = new SM2ParameterSpec(userId);
Signature verifier = Signature.getInstance("SM3withSM2", "BC");
verifier.setParameter(parameterSpec);
verifier.initVerify(publicKey);
verifier.update(msg, 0, msg.length);
return verifier.verify(rs);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] changeC1C2C3ToC1C3C2(byte[] c1c2c3) {
int c1Len = (x9ECParameters.getCurve().getFieldSize() + 7) / 8 * 2 + 1;
byte[] result = new byte[c1c2c3.length];
System.arraycopy(c1c2c3, 0, result, 0, c1Len);
System.arraycopy(c1c2c3, c1c2c3.length - 32, result, c1Len, 32);
System.arraycopy(c1c2c3, c1Len, result, c1Len + 32, c1c2c3.length - c1Len - 32);
return result;
}
public static byte[] changeC1C3C2ToC1C2C3(byte[] c1c3c2) {
int c1Len = (x9ECParameters.getCurve().getFieldSize() + 7) / 8 * 2 + 1;
byte[] result = new byte[c1c3c2.length];
System.arraycopy(c1c3c2, 0, result, 0, c1Len);
System.arraycopy(c1c3c2, c1Len + 32, result, c1Len, c1c3c2.length - c1Len - 32);
System.arraycopy(c1c3c2, c1Len, result, c1c3c2.length - 32, 32);
return result;
}
public static byte[] sm2Decrypt(byte[] data, PrivateKey key) {
return sm2DecryptOld(changeC1C3C2ToC1C2C3(data), key);
}
public static byte[] sm2Encrypt(byte[] data, PublicKey key) {
return changeC1C2C3ToC1C3C2(sm2EncryptOld(data, key));
}
public static byte[] sm2EncryptOld(byte[] data, PublicKey key) {
BCECPublicKey localECPublicKey = (BCECPublicKey) key;
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), ecDomainParameters);
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
try {
return sm2Engine.processBlock(data, 0, data.length);
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
public static byte[] sm2DecryptOld(byte[] data, PrivateKey key) {
BCECPrivateKey localECPrivateKey = (BCECPrivateKey) key;
ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(localECPrivateKey.getD(), ecDomainParameters);
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(false, ecPrivateKeyParameters);
try {
return sm2Engine.processBlock(data, 0, data.length);
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
public static byte[] sm4Encrypt(byte[] keyBytes, byte[] plain) {
byte[] keyBytes0;
if (keyBytes.length != 16) {
keyBytes0 = new byte[16];
for (int i = 0; i < keyBytes0.length; ++i) {
if (keyBytes.length > i) {
keyBytes0[i] = keyBytes[i];
}
}
keyBytes = keyBytes0;
}
if (plain.length % 16 != 0) {
keyBytes0 = new byte[16 * (plain.length / 16 + 1)];
System.arraycopy(plain, 0, keyBytes0, 0, plain.length);
plain = keyBytes0;
}
try {
Key key = new SecretKeySpec(keyBytes, "SM4");
Cipher out = Cipher.getInstance("SM4/ECB/NoPadding", "BC");
out.init(1, key);
return out.doFinal(plain);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] sm4Decrypt(byte[] keyBytes, byte[] cipher) {
byte[] keyBytes0;
if (keyBytes.length != 16) {
keyBytes0 = new byte[16];
for (int i = 0; i < keyBytes0.length; ++i) {
if (keyBytes.length > i) {
keyBytes0[i] = keyBytes[i];
}
}
keyBytes = keyBytes0;
}
if (cipher.length % 16 != 0) {
keyBytes0 = new byte[16 * (cipher.length / 16 + 1)];
System.arraycopy(cipher, 0, keyBytes0, 0, cipher.length);
cipher = keyBytes0;
}
try {
Key key = new SecretKeySpec(keyBytes, "SM4");
Cipher in = Cipher.getInstance("SM4/ECB/NoPadding", "BC");
in.init(2, key);
byte[] bytes = in.doFinal(cipher);
for (int i = bytes.length - 1; i >= 0; --i) {
if (bytes[i] != 0) {
byte[] bytes1 = new byte[i + 1];
System.arraycopy(bytes, 0, bytes1, 0, i + 1);
bytes = bytes1;
i = -1;
}
}
return bytes;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String sm4Encrypt(String key, String plan) {
byte[] keyBytes = new byte[16];
byte[] keyBytes0 = key.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < keyBytes.length; ++i) {
if (keyBytes0.length > i) {
keyBytes[i] = keyBytes0[i];
}
}
byte[] cipher = plan.getBytes(StandardCharsets.UTF_8);
byte[] bytes = sm4Encrypt(keyBytes, cipher);
return Hex.toHexString(bytes).toUpperCase();
}
public static String sm4Decrypt(String key, String cipher) {
byte[] keyBytes = new byte[16];
byte[] keyBytes0 = key.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < keyBytes.length; ++i) {
if (keyBytes0.length > i) {
keyBytes[i] = keyBytes0[i];
}
}
byte[] cipherbytes = Hex.decode(cipher);
byte[] bytes = sm4Decrypt(keyBytes, cipherbytes);
return new String(bytes, StandardCharsets.UTF_8);
}
private static byte[] bigIntToFixexLengthBytes(BigInteger rOrS) {
byte[] rs = rOrS.toByteArray();
if (rs.length == 32) {
return rs;
} else if (rs.length == 33 && rs[0] == 0) {
return Arrays.copyOfRange(rs, 1, 33);
} else if (rs.length < 32) {
byte[] result = new byte[32];
Arrays.fill(result, (byte) 0);
System.arraycopy(rs, 0, result, 32 - rs.length, rs.length);
return result;
} else {
throw new RuntimeException("err rs: " + Hex.toHexString(rs));
}
}
private static byte[] rsAsn1ToPlainByteArray(byte[] rsDer) {
ASN1Sequence seq = ASN1Sequence.getInstance(rsDer);
byte[] r = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
byte[] s = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(1)).getValue());
byte[] result = new byte[64];
System.arraycopy(r, 0, result, 0, r.length);
System.arraycopy(s, 0, result, 32, s.length);
return result;
}
private static byte[] rsPlainByteArrayToAsn1(byte[] sign) {
if (sign.length != 64) {
throw new RuntimeException("err rs. ");
} else {
BigInteger r = new BigInteger(1, Arrays.copyOfRange(sign, 0, 32));
BigInteger s = new BigInteger(1, Arrays.copyOfRange(sign, 32, 64));
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
try {
return (new DERSequence(v)).getEncoded("DER");
} catch (IOException var5) {
throw new RuntimeException(var5);
}
}
}
public static BCECPrivateKey getPrivatekeyFromD(BigInteger d) {
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecParameterSpec);
return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
}
public static PublicKey getPublickeyFromX509File(File file) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
FileInputStream in = new FileInputStream(file);
X509Certificate x509 = (X509Certificate) cf.generateCertificate(in);
return x509.getPublicKey();
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
static {
ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
ecParameterSpec = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
if (Security.getProvider("BC") == null) {
Security.addProvider(new BouncyCastleProvider());
}
}
}
4. 相关配置
package cn.bridgeli.demo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "xyhn")
//@RefreshScope
public class XyhnConfig {
private String userId;
private String platformId;
private String appKey;
private String priKey;
private String wsAddr;
private String namespaceURI;
private String pubKeyPath;
private String queryAppKey;
private String queryPriKey;
private String queryWsAddr;
private String queryNamespaceURI;
private String queryPubKeyPath;
}
以上是上报和查询数据的核心方法,下面是查询具体数据的封装
5. 查询的接口:
package cn.bridgeli.demo;
public interface XyhnService {
Response queryDatas(String param, String page, String size);
}
package cn.bridgeli.demo;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public abstract class AbstractXyhnService implements XyhnService {
// private static ICompInfoService compInfoService = SpringUtils.getBean(ICompInfoService.class);
@Override
public Response queryDatas(String enterpriseName, String page, String size) {
CompInfo compInfoParam = new CompInfo();
// compInfoParam.setEnterpriseName(enterpriseName);
// List<CompInfo> compInfos = compInfoService.selectCompInfoList(compInfoParam);
// CompInfo compInfo = null;
// if (CollectionUtils.isEmpty(compInfos)) {
// compInfo = new CompInfo();
// compInfo.setEnterpriseName(enterpriseName);
// } else {
// compInfo = compInfos.get(0);
// }
List<QueryParam> list = buildQueryParam(compInfoParam);
QueryParam isDeleteParam = new QueryParam();
isDeleteParam.setField_value("0");
isDeleteParam.setField_name("$$_ISDELETE");
isDeleteParam.setField_type("String");
isDeleteParam.setField_symbol("=");
list.add(isDeleteParam);
QueryParam stateParam = new QueryParam();
stateParam.setField_value("0");
stateParam.setField_name("$$_STATE");
stateParam.setField_type("String");
stateParam.setField_symbol("=");
list.add(stateParam);
if (StringUtils.isBlank(size) || StringUtils.isBlank(page)) {
size = "20";
page = "1";
}
JSONObject jsonObject = new JSONObject();
buildTableIdParam(jsonObject);
jsonObject.put("query", list);
jsonObject.put("page", page);
jsonObject.put("size", size);
buildSortParam(jsonObject);
String data = XyhnUtil.queryData("queryPageDataByTableId", jsonObject);
return parseXml(data);
}
protected abstract List<QueryParam> buildQueryParam(CompInfo compInfo);
protected abstract void buildTableIdParam(JSONObject jsonObject);
protected abstract void buildSortParam(JSONObject jsonObject);
public static Response parseXml(String xmlContent) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = null;
try {
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(new InputSource(new StringReader(xmlContent)));
} catch (ParserConfigurationException e) {
log.error("ParserConfigurationException", e);
} catch (IOException e) {
log.error("IOException", e);
} catch (SAXException e) {
log.error("SAXException", e);
}
if (null == doc) {
return null;
}
Response response = new Response();
Element root = doc.getDocumentElement();
Element datas = (Element) root.getElementsByTagName("datas").item(0);
// Extract items
NodeList rowList = datas.getElementsByTagName("row");
if (rowList.getLength() <= 0) {
return response;
}
List<Map<String, String>> items = new ArrayList<>();
for (int i = 0; i < rowList.getLength(); i++) {
Element row = (Element) rowList.item(i);
NodeList itemList = row.getElementsByTagName("item");
if (itemList.getLength() == 0) {
continue;
}
Map<String, String> itemMap = new HashMap<>();
for (int j = 0; j < itemList.getLength(); j++) {
Element item = (Element) itemList.item(j);
String key = item.getAttribute("field");
String value = item.getTextContent();
itemMap.put(key, value);
}
items.add(itemMap);
}
response.setData(items);
// Extract attributes from the 'datas' tag
NamedNodeMap attrs = datas.getAttributes();
response.setStartIndex(Integer.parseInt(attrs.getNamedItem("startIndex").getNodeValue()));
response.setTotalPage(Integer.parseInt(attrs.getNamedItem("totalPage").getNodeValue()));
response.setTotalSize(Integer.parseInt(attrs.getNamedItem("totalSize").getNodeValue()));
response.setTime(Integer.parseInt(attrs.getNamedItem("time").getNodeValue()));
response.setSize(Integer.parseInt(attrs.getNamedItem("size").getNodeValue()));
log.info("解析成对象之后: " + JSONObject.toJSONString(response));
return response;
}
}
查询的具体实现主要分三种:
① 普通查询,即公开公示的接口:
package cn.bridgeli.demo;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class GsAoOpaDetailServiceImpl extends AbstractXyhnService {
@Override
protected List<QueryParam> buildQueryParam(CompInfo compInfo) {
QueryParam queryParam = new QueryParam();
queryParam.setField_value(compInfo.getEnterpriseName());
queryParam.setField_type("String");
queryParam.setField_symbol("=");
queryParam.setField_name("ENTNAME");
return Stream.of(queryParam).collect(Collectors.toList());
}
@Override
protected void buildTableIdParam(JSONObject jsonObject) {
jsonObject.put("tableId", "");
}
@Override
protected void buildSortParam(JSONObject jsonObject) {
// jsonObject.put("sort", Stream.of("$$_MDATE").collect(Collectors.toList()));
}
}
② 普通授权接口
package cn.bridgeli.demo;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class ZxqySbbxfjnServiceImpl extends AbstractXyhnService {
@Resource
private XYHNConfig xyhnConfig;
@Override
protected List<QueryParam> buildQueryParam(CompInfo compInfo) {
if (!"0".equals(compInfo.getCancelAuthState())) {
throw new ServiceException("接口未授权,请先授权");
}
String licenseId = compInfo.getLicenseId();
if (StringUtils.isBlank(licenseId)) {
throw new ServiceException("接口未授权,无法调用");
}
QueryParam queryParam = new QueryParam();
queryParam.setField_value(compInfo.getEnterpriseName());
queryParam.setField_type("String");
queryParam.setField_symbol("=");
queryParam.setField_name("enterpriseName");
QueryParam licenseIdParam = new QueryParam();
licenseIdParam.setField_value(licenseId);
licenseIdParam.setField_name("licenseId");
licenseIdParam.setField_type("String");
licenseIdParam.setField_symbol("=");
QueryParam uniscIdParam = new QueryParam();
uniscIdParam.setField_value(compInfo.getUniscId());
uniscIdParam.setField_name("uniscId");
uniscIdParam.setField_type("String");
uniscIdParam.setField_symbol("=");
QueryParam platformIdParam = new QueryParam();
platformIdParam.setField_value(xyhnConfig.getPlatformId());
platformIdParam.setField_name("platformId");
platformIdParam.setField_type("String");
platformIdParam.setField_symbol("=");
QueryParam searchOrgCodeParam = new QueryParam();
// searchOrgCodeParam.setField_value(compInfo.getAuthorizedOrgsCode());
searchOrgCodeParam.setField_name("searchOrgCode");
searchOrgCodeParam.setField_type("String");
searchOrgCodeParam.setField_symbol("=");
return Stream.of(queryParam, licenseIdParam, uniscIdParam, platformIdParam, searchOrgCodeParam).collect(Collectors.toList());
}
@Override
protected void buildTableIdParam(JSONObject jsonObject) {
jsonObject.put("tableId", "");
}
@Override
protected void buildSortParam(JSONObject jsonObject) {
}
}
③ 省授权接口
package cn.bridgeli.demo;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class SrstCbdwsbjfxxServiceImpl extends AbstractXyhnService {
@Resource
private XYHNConfig xyhnConfig;
// searchSubject 和 searchSubjectCode,对应 getAuth 接口的 searchSubject 和 searchSubjectCode
@Override
protected List<QueryParam> buildQueryParam(CompInfo compInfo) {
String authId = compInfo.getAuthId();
if (StringUtils.isBlank(authId)) {
throw new ServiceException("请先获取省授权");
}
Date validDate = compInfo.getValidDate();
QueryParam searchSubjectParam = new QueryParam();
searchSubjectParam.setField_value(compInfo.getEnterpriseName());
searchSubjectParam.setField_type("String");
searchSubjectParam.setField_symbol("=");
searchSubjectParam.setField_name("aab004");
QueryParam searchSubjectCodeParam = new QueryParam();
searchSubjectCodeParam.setField_value(compInfo.getUniscId());
searchSubjectCodeParam.setField_type("String");
searchSubjectCodeParam.setField_symbol("=");
searchSubjectCodeParam.setField_name("aab039");
QueryParam authKeyParam = new QueryParam();
authKeyParam.setField_value(xyhnConfig.getQueryAppKey());
authKeyParam.setField_name("authKey");
authKeyParam.setField_type("String");
authKeyParam.setField_symbol("=");
QueryParam authIDParam = new QueryParam();
authIDParam.setField_value(authId);
authIDParam.setField_name("authID");
authIDParam.setField_type("String");
authIDParam.setField_symbol("=");
return Stream.of(searchSubjectParam, searchSubjectCodeParam, authKeyParam, authIDParam).collect(Collectors.toList());
}
@Override
protected void buildTableIdParam(JSONObject jsonObject) {
jsonObject.put("tableId", "");
}
@Override
protected void buildSortParam(JSONObject jsonObject) {
}
}
6. 查询参数的封装:
package cn.bridgeli.demo;
import lombok.Data;
@Data
public class QueryParam {
private String field_name;
private String field_type;
private String field_value;
private String field_symbol;
private String field_grantmapping;
}
7. 返回值的封装
package cn.bridgeli.demo;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class Response {
private Integer startIndex;
private Integer totalPage;
private Integer totalSize;
private Integer time;
private Integer size;
private List<Map<String, String>> data;
}
8. 接口类型
package cn.bridgeli.demo;
import lombok.Getter;
@Getter
public enum FaGaiWeiInterfaceEnum {
gsQyjbxxServiceImpl("社会公开", "工商企业基本信息(带行业代码)"),
zxqyQysfqsServiceImpl("授权查询", "中小企业融资-企业是否欠税"),
zrtBdcqdjxxFdcqServiceImpl("授权查询", "不动产_不动产权登记信息_房地产权信息-省授权"),
mztHydjxxServiceImpl("社会公开", "婚姻登记信息-省授权"),
;
FaGaiWeiInterfaceEnum(String openType, String description) {
this.openType = openType;
this.description = description;
}
private final String openType;
private final String description;
}
最后也必须要说明的是,这段代码是我随手从项目中摘出来的,并不完全,也会存在很多问题,但思路是没错的,代码也存在很大的优化空间.
全文完,如果本文对您有所帮助,请花 1 秒钟帮忙点击一下广告,谢谢。
作 者: BridgeLi,https://www.bridgeli.cn
原文链接:http://www.bridgeli.cn/archives/764
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
作 者: BridgeLi,https://www.bridgeli.cn
原文链接:http://www.bridgeli.cn/archives/764
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
近期评论