parent
f781bc633a
commit
2892048cf4
@ -0,0 +1,288 @@ |
||||
package com.sinosoft.lis.wsclient; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.http.HttpClient; |
||||
import java.net.http.HttpRequest; |
||||
import java.net.http.HttpResponse; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 询价计划信息服务 |
||||
* 调用外部WebService接口查询AskPlan信息 |
||||
*/ |
||||
@Service |
||||
public class AskPlanInfoService { |
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AskPlanInfoService.class); |
||||
|
||||
// 接口地址
|
||||
private static final String WS_URL = "http://112.124.61.57:9998/ws/dealDataWebService"; |
||||
|
||||
// 业务参数
|
||||
private static final String SYS_CODE = "GCS2ASK20191123000001"; |
||||
private static final String FUNC_FLAG = "GRFQ000002"; |
||||
|
||||
// SOAP命名空间(根据实际WSDL调整)
|
||||
private static final String SOAP_NAMESPACE = "http://webservice.sinosoft.com.cn"; |
||||
|
||||
/** |
||||
* 查询询价计划信息 |
||||
* |
||||
* @param askNo 询价单号(如:17751055) |
||||
* @return 响应XML字符串,失败返回null |
||||
*/ |
||||
public String queryAskPlanInfo(String askNo, String batchNo) { |
||||
// 参数校验
|
||||
if (askNo == null || askNo.trim().isEmpty()) { |
||||
log.error("查询AskPlanInfo失败:askNo参数为空"); |
||||
return null; |
||||
} |
||||
if (batchNo == null || batchNo.trim().isEmpty()) { |
||||
log.error("查询AskPlanInfo失败:batchNo参数为空"); |
||||
return null; |
||||
} |
||||
|
||||
log.info("开始查询AskPlanInfo,询价单号: {},批次号: {}", askNo,batchNo); |
||||
|
||||
try { |
||||
// 1. 构建业务XML(CDATA中的内容)
|
||||
String businessXml = buildBusinessXml(askNo, batchNo); |
||||
log.debug("业务XML:\n{}", businessXml); |
||||
|
||||
// 2. 构建SOAP请求(业务XML放在CDATA中)
|
||||
String soapRequest = buildSoapRequest(businessXml); |
||||
log.info("SOAP请求:\n{}", soapRequest); |
||||
|
||||
// 3. 发送SOAP请求
|
||||
String soapResponse = sendSoapRequest(soapRequest); |
||||
if (soapResponse == null) { |
||||
log.error("SOAP请求返回空响应"); |
||||
return null; |
||||
} |
||||
log.info("SOAP响应:\n{}", soapResponse); |
||||
|
||||
// 4. 从SOAP响应中提取业务响应
|
||||
String businessResponse = extractBusinessResponse(soapResponse); |
||||
if (businessResponse == null) { |
||||
log.error("提取业务响应失败"); |
||||
return null; |
||||
} |
||||
log.info("业务响应:\n{}", businessResponse); |
||||
|
||||
// 5. 检查业务返回码
|
||||
String returnCode = extractXmlValue(businessResponse, "ReturnCode"); |
||||
if ("000000".equals(returnCode)) { |
||||
log.info("查询成功,询价单号: {}", askNo); |
||||
} else { |
||||
String message = extractXmlValue(businessResponse, "Message"); |
||||
log.warn("查询返回非成功状态,返回码: {}, 消息: {}", returnCode, message); |
||||
} |
||||
|
||||
return businessResponse; |
||||
|
||||
} catch (Exception e) { |
||||
log.error("查询AskPlanInfo异常,询价单号: {}", askNo, e); |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 构建业务XML(将被放在CDATA中) |
||||
*/ |
||||
private String buildBusinessXml(String askNo, String batchNo) { |
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); |
||||
SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss"); |
||||
Date now = new Date(); |
||||
|
||||
StringBuilder xml = new StringBuilder(); |
||||
xml.append("<?xml version=\"1.0\" encoding=\"GBK\"?>\n"); |
||||
xml.append("<TX>\n"); |
||||
xml.append(" <ENTITY>\n"); |
||||
xml.append(" <TRANSHEAD>\n"); |
||||
xml.append(" <SysCode>").append(SYS_CODE).append("</SysCode>\n"); |
||||
xml.append(" <FuncFlag>").append(FUNC_FLAG).append("</FuncFlag>\n"); |
||||
xml.append(" <TransDate>").append(dateFormat.format(now)).append("</TransDate>\n"); |
||||
xml.append(" <TransTime>").append(timeFormat.format(now)).append("</TransTime>\n"); |
||||
xml.append(" </TRANSHEAD>\n"); |
||||
xml.append(" <TRANSBODY>\n"); |
||||
xml.append(" <AskNo>").append(escapeXml(askNo)).append("</AskNo>\n"); |
||||
xml.append(" <AskBatchNo>").append(escapeXml(batchNo)).append("</AskBatchNo>\n"); |
||||
// xml.append(" <PolApplyDate>").append(dateFormat.format(now)).append("</PolApplyDate>\n"); // 改成 yyyyMMdd
|
||||
xml.append(" <PolApplyDate></PolApplyDate>\n"); // 改成 yyyyMMdd
|
||||
xml.append(" </TRANSBODY>\n"); |
||||
xml.append(" </ENTITY>\n"); |
||||
xml.append("</TX>"); |
||||
|
||||
return xml.toString(); |
||||
} |
||||
/** |
||||
* 构建SOAP请求(CDATA包装业务XML) |
||||
*/ |
||||
private String buildSoapRequest(String businessXml) { |
||||
StringBuilder soap = new StringBuilder(); |
||||
soap.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
||||
soap.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"); |
||||
soap.append(" xmlns:web=\"").append(SOAP_NAMESPACE).append("\">\n"); |
||||
soap.append(" <soapenv:Header/>\n"); |
||||
soap.append(" <soapenv:Body>\n"); |
||||
soap.append(" <web:queryAskPlanInfo>\n"); |
||||
soap.append(" <arg0><![CDATA[").append(businessXml).append("]]></arg0>\n"); |
||||
soap.append(" </web:queryAskPlanInfo>\n"); |
||||
soap.append(" </soapenv:Body>\n"); |
||||
soap.append("</soapenv:Envelope>"); |
||||
|
||||
return soap.toString(); |
||||
} |
||||
|
||||
/** |
||||
* 发送SOAP请求 |
||||
*/ |
||||
private String sendSoapRequest(String soapRequest) { |
||||
try { |
||||
// 创建HttpClient
|
||||
HttpClient client = HttpClient.newBuilder() |
||||
.connectTimeout(java.time.Duration.ofSeconds(30)) |
||||
.build(); |
||||
|
||||
// 构建HttpRequest
|
||||
HttpRequest request = HttpRequest.newBuilder() |
||||
.uri(URI.create(WS_URL)) |
||||
.header("Content-Type", "text/xml; charset=UTF-8") |
||||
.header("SOAPAction", "") |
||||
.POST(HttpRequest.BodyPublishers.ofString(soapRequest, StandardCharsets.UTF_8)) |
||||
.build(); |
||||
|
||||
// 发送请求
|
||||
HttpResponse<String> response = client.send(request, |
||||
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); |
||||
|
||||
int statusCode = response.statusCode(); |
||||
log.info("HTTP响应状态码: {}", statusCode); |
||||
|
||||
if (statusCode != 200) { |
||||
log.error("HTTP请求失败,状态码: {}, 响应: {}", statusCode, response.body()); |
||||
return null; |
||||
} |
||||
|
||||
String responseBody = response.body(); |
||||
|
||||
// 检查是否有SOAP错误
|
||||
if (responseBody.contains("<soap:Fault>") || responseBody.contains("<soapenv:Fault>")) { |
||||
log.error("SOAP调用失败: {}", responseBody); |
||||
return null; |
||||
} |
||||
|
||||
return responseBody; |
||||
|
||||
} catch (IOException | InterruptedException e) { |
||||
log.error("发送SOAP请求异常", e); |
||||
Thread.currentThread().interrupt(); |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
private String extractBusinessResponse(String soapResponse) { |
||||
if (soapResponse == null) { |
||||
return null; |
||||
} |
||||
|
||||
// 查找 <return> 标签
|
||||
String startTag = "<return>"; |
||||
String endTag = "</return>"; |
||||
|
||||
int startIdx = soapResponse.indexOf(startTag); |
||||
if (startIdx == -1) { |
||||
log.warn("未找到<return>标签"); |
||||
return soapResponse; |
||||
} |
||||
|
||||
int endIdx = soapResponse.indexOf(endTag, startIdx); |
||||
if (endIdx == -1) { |
||||
log.warn("未找到</return>标签"); |
||||
return soapResponse; |
||||
} |
||||
|
||||
// 提取并反转义
|
||||
String escapedXml = soapResponse.substring(startIdx + startTag.length(), endIdx); |
||||
String unescapedXml = unescapeXml(escapedXml); |
||||
|
||||
log.debug("提取的业务响应:\n{}", unescapedXml); |
||||
return unescapedXml; |
||||
} |
||||
|
||||
/** |
||||
* XML反转义(完整版) |
||||
*/ |
||||
private String unescapeXml(String text) { |
||||
if (text == null) { |
||||
return null; |
||||
} |
||||
|
||||
// 先替换字符实体(注意顺序:& 要最后处理,避免重复替换)
|
||||
String result = text |
||||
.replace("<", "<") |
||||
.replace(">", ">") |
||||
.replace(""", "\"") |
||||
.replace("'", "'") |
||||
.replace(" ", "\r") // 回车 CR (十进制)
|
||||
.replace(" ", "\n") // 换行 LF (十进制)
|
||||
.replace("
", "\r") // 回车 CR (十六进制小写)
|
||||
.replace("
", "\r") // 回车 CR (十六进制大写)
|
||||
.replace("
", "\n") // 换行 LF (十六进制小写)
|
||||
.replace("
", "\n") // 换行 LF (十六进制大写)
|
||||
.replace("&", "&"); // & 符号最后处理
|
||||
|
||||
// 可选:移除或替换特殊控制字符
|
||||
result = result |
||||
.replace("\r\n", "\n") // 统一换行符
|
||||
.replace("\r", "\n"); // 单独的回车也转成换行
|
||||
|
||||
return result; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 从XML中提取指定标签的值 |
||||
*/ |
||||
private String extractXmlValue(String xml, String tag) { |
||||
if (xml == null || tag == null) { |
||||
return ""; |
||||
} |
||||
|
||||
String startTag = "<" + tag + ">"; |
||||
String endTag = "</" + tag + ">"; |
||||
|
||||
int startIdx = xml.indexOf(startTag); |
||||
if (startIdx == -1) { |
||||
return ""; |
||||
} |
||||
|
||||
int endIdx = xml.indexOf(endTag, startIdx); |
||||
if (endIdx == -1) { |
||||
return ""; |
||||
} |
||||
|
||||
return xml.substring(startIdx + startTag.length(), endIdx); |
||||
} |
||||
|
||||
/** |
||||
* XML特殊字符转义 |
||||
*/ |
||||
private String escapeXml(String text) { |
||||
if (text == null) { |
||||
return ""; |
||||
} |
||||
return text.replace("&", "&") |
||||
.replace("<", "<") |
||||
.replace(">", ">") |
||||
.replace("\"", """) |
||||
.replace("'", "'"); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue