全国中小企业融资综合信用服务平台-省级节点数据接口规范-河南省营商环境和社会信用建设中心
开始之前先说一点题外话,几年前曾经看过一个视频,其中一个观点大概就是程序员是一个反传统的群体,其他群体掌握了某个技术,一般都是当做内部商业机密,而程序员则不一样,喜欢开源,尤其 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
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
近期评论