一,业务场景:
支付中心项目,oa发送支付请求到支付中心,支付完成要给oa回复,这个回复就是用webservice发送的。
我方相当于一个webservice客户端,oa相当于服务端。
二,我需要知道什么
*WSDL地址:
http://10.188.2.93:8081//services/PayService?wsdl
实现方式一,
根据以往的经验,通过webService调用接口
*用命令解析wsdl文件,生成客户端代码 wmimport -keep url
*调用客户端代码中的接口,访问服务端
参考下文
https://www.cnblogs.com/xdp-gacl/p/4260627.html
但是我们这个项目没有解析wsdl文件, 没有使用解析的客户端代码
实现方式二,基于axis实现,本项目采用这种方式实现
可参考:
https://blog.csdn.net/qq_33236248/article/details/80436688
*依赖
compile('com.liferay:org.apache.axis:1.4.LIFERAY-PATCHED-3')
compile('axis:axis-wsdl4j:1.5.1')
compile('commons-discovery:commons-discovery:20040218.194635')
*包装请求参数
定义参数格式,是OA方要求还是,我方定义好通知OA?
请求参数:需要给OA的
// OA付款申请编号
private String oaCode;
// 支付状态
private String payStatus;
// 付款时间
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date paymentDate;
@JsonFormat注解作用:
https://www.cnblogs.com/woshimrf/p/5189435.html
三,代码实现
1,封装请求参数
*原始请求参数
public class CallOaRequest {
// OA付款申请编号
private String oaCode;
// 支付状态
private String payStatus;
// 付款时间
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date paymentDate;
*封装1
public class ReqData implements Serializable {
private static final long serialVersionUID = 6648835178847199263L;
@JsonProperty("list")
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
*封装2
public class ReqService implements Serializable {
private static final long serialVersionUID = -8153707350660508556L;
@JsonProperty("Request")
private ReqData request;
public ReqData getRequest() {
return request;
}
public void setRequest(ReqData request) {
this.request = request;
}
}
*封装3
@XmlRootElement
public class RestRequest implements Serializable {
private static final long serialVersionUID = -4637756210826669082L;
@JsonProperty("Service")
private ReqService reqService;
public ReqService getReqService() {
return reqService;
}
public void setReqService(ReqService reqService) {
this.reqService = reqService;
}
}
2,业务代码调用工具类
*查询数据,获取webservice入参
同一个oa付款申请编号下,所有数据都支付完成,才可以发送给oa
相比以往处理方式,可使用stream分组
/**
* 通知【OA】支付结果
*
* @param ids
* @return
*/
@Override
public String callOaPaymentResult(List ids) {
List voList = syncAccountService.getWaitSyncOaList(ids);
//oa_code oa付款申请编号
Map> groupBy = voList.stream().collect(Collectors.groupingBy(AccountSyncVo::getOaCode));
ArrayList> arrayList = new ArrayList<>(groupBy.values());
ArrayList> arrayList2 = new ArrayList<>(groupBy.values());
for (List syncVos : arrayList) {
for (AccountSyncVo vo : syncVos) {
if (!Const.PAYSTATUS.equals(vo.getPayStatus())) {
arrayList2.remove(syncVos);
break;
}
}
}
List requestList = new ArrayList<>();
List oaCodes = new ArrayList<>();
for (List entities2 : arrayList2) {
entities2 = entities2.stream().sorted(Comparator.comparing(AccountSyncVo::getPaymentDate).reversed()).collect(Collectors.toList());
AccountSyncVo syncVo = entities2.get(0);
CallOaRequest request = new CallOaRequest();
BeanUtils.copyProperties(syncVo, request);
request.setPayStatus("已完成");
requestList.add(request);
// OA付款申请编号
oaCodes.add(syncVo.getOaCode());
}
StringBuilder sb = new StringBuilder();
if (requestList.size() > 0) {
List failureOaCodes = new ArrayList<>();
List responseVos = externalApiService.pushMsgToOa(requestList);
if (responseVos == null || responseVos.size() == 0) {
failureOaCodes.addAll(oaCodes);
oaCodes.clear();
} else {
for (OaResponseVo vo : responseVos) {
if (!StringUtils.isEmpty(vo.getStatus()) && Const.FAILURE.equals(vo.getStatus())) {
failureOaCodes.add(vo.getOaCode());
String str = "OA申请编号为【" + vo.getOaCode() + "】的数据:" + vo.getMsg() + "\n";
sb.append(str);
}
}
oaCodes.removeAll(failureOaCodes);
}
if (oaCodes.size() > 0) {
syncAccountService.updateSyncOaStatus(oaCodes, 1);
}
if (failureOaCodes.size() > 0) {
syncAccountService.updateSyncOaStatus(failureOaCodes, 2);
}
}
return sb.toString();
}
*封装请求参数
@Slf4j
@Service
public class ExternalApiServiceImpl implements ExternalApiService {
@Value("${PAYMENT_APPLY_OA_URL}")
private String applyOaUrl;
@Value("${PAYMENT_APPLY_ORACLE_URL}")
private String applyOracleUrl;
@Value("${PAYMENT_ORACLE_USERNAME}")
private String oracleUsername;
@Value("${PAYMENT_ORACLE_PASSWORD}")
private String oraclePassword;
@Autowired
private ExternalApiMapper externalApiMapper;
@Autowired
private AccountMapper accountMapper;
@Autowired
private OaMiddleMapper oaMiddleMapper;
/**
* 推送Oracle支付结果到OA
*
* @param oaRequestList
* @return
*/
@Override
public List pushMsgToOa(List oaRequestList) {
log.info(">>>>>> 开始请求访问 [ OA ] 接口: URL == " + applyOaUrl);
RestRequest restRequest = new RestRequest();
ReqService reqService = new ReqService();
ReqData reqData = new ReqData();
reqData.setList(oaRequestList);
restRequest.setReqService(reqService);
reqService.setRequest(reqData);
List voList;
try {
ObjectMapper objectMapper = new ObjectMapper();
//objectMapper转化为json字符串
String object = objectMapper.writeValueAsString(restRequest);
log.info(">>>>> apply [OA]<<<<< object == " + object);
String response = HttpPostUtil.getServiceClient(applyOaUrl, object);
if (StringUtils.isEmpty(response)) {
return null;
}
System.out.println("<---[OA]---> response: " + response);
JSONObject oaMsg = JSONObject.parseObject(response);
JSONObject serviceRegion = (JSONObject) oaMsg.get("Service");
JSONArray responseRegion = (JSONArray) serviceRegion.get("Response");
voList = JSONObject.parseArray(responseRegion.toJSONString(), OaResponseVo.class);
} catch (Exception e) {
log.error("对外接口【OA】访问异常:");
e.printStackTrace();
return null;
}
return voList;
}
/**
* 推送OA支付请求到Oracle
*
* @param request
* @return
*/
@Override
public String pushMsgToOracle(CallOracleRequest request) {
log.info(">>>>>> 开始请求访问 [ Oracle ] 接口: URL == " + applyOracleUrl);
OracleRequest oracleRequest = new OracleRequest();
OracleInput oracleInput = new OracleInput();
OracleParameters parameters = new OracleParameters();
BeanUtils.copyProperties(request, parameters);
OracleRestHeader restHeader = new OracleRestHeader();
// 封装请求头(此处请求头非Http请求头),请求体(非http请求体此处只有请求入参,http请求体包含此处请求+请求体)
oracleInput.setRestHeader(restHeader);
oracleInput.setParameters(parameters);
oracleRequest.setOracleInput(oracleInput);
try {
ObjectMapper objectMapper = new ObjectMapper();
String object = objectMapper.writeValueAsString(oracleRequest);
log.info(">>>>apply[Oracle]<<<< object == " + object);
String up = oracleUsername + ":" + oraclePassword;
String response = HttpPostUtil.getHttpClient(applyOracleUrl, object, up);
System.out.println("<---[Oracle]---> response: " + response);
JSONObject oracleMsg = JSONObject.parseObject(response);
JSONObject outputParameters = (JSONObject) oracleMsg.get("OutputParameters");
//oracle响应码响应消息
String status = (String) outputParameters.get("X_RETURN_STATUS");
String msg = (String) outputParameters.get("X_MSG_DATA");
log.info(">>>>>> 收到来自【Oracle】的响应:msg == " + msg);
if (StringUtils.isNotEmpty(status) && !Const.S.equals(status)) {
return msg;
}
} catch (Exception e) {
log.error("对外接口【Oracle】访问异常");
e.printStackTrace();
return "E";
}
return "";
}
3,webservice工具类
/**
* webService
*
* @param path url
* @param stringObject 入参
* @return
*/
public static String getServiceClient(String path, String stringObject) {
String response = "";
try {
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(path);
call.setOperationName(new QName("weaver.zzn.aj", "payResult"));
Object[] param = new Object[]{stringObject};
response = (String) call.invoke(param);
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
public class HttpPostUtil {
private static final String BASICAUTH = "AN_JI:AJ_1113";
/**
* webService
*
* @param path url
* @param stringObject 入参
* @return
*/
public static String getServiceClient(String path, String stringObject) {
String response = "";
try {
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(path);
call.setOperationName(new QName("weaver.zzn.aj", "payResult"));
Object[] param = new Object[]{stringObject};
response = (String) call.invoke(param);
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
public static void main(String[] args) {
try {
//字符集
String encodingStyle = "utf-8";
//WSDL的地址
String endpoint = "http://www.webxml.com.cn/WebServices/RandomFontsWebService.asmx?wsdl";
//命名空间,在WSDL中对应的标签是:参见说明第3条
String targetNamespace = "http://WebXml.com.cn/";
//具体方法的调用URI,在WSDL中对应的标签是:参见说明第4条
String soapActionURI = "http://WebXml.com.cn/getCharFonts";
//具体调用的方法名,在WSDL中对应的标签是:参见说明第5条
String method = "getCharFonts";
//调用接口的参数的名字
String[] paramNames = {"byFontsLength"};
//调用接口的参数的值
Integer[] paramValues = {1};
Service service = new Service();
Call call = (Call) service.createCall();
// call.setTimeout(new Integer(20000)); //设置超时时间
call.setSOAPActionURI(soapActionURI);
call.setTargetEndpointAddress(new java.net.URL(endpoint)); //设置目标接口的地址
call.setEncodingStyle(encodingStyle);//设置传入服务端的字符集格式如utf-8等
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//返回值类型:String
call.setOperationName(new QName(targetNamespace, method));// 具体调用的方法名,可以由接口提供方告诉你,也可以自己从WSDL中找
call.setUseSOAPAction(true);
call.addParameter(new QName(targetNamespace, paramNames[0]),
org.apache.axis.encoding.XMLType.XSD_INTEGER,
javax.xml.rpc.ParameterMode.IN);// 接口的参数
// call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);// 设置返回类型 ,如String
call.setReturnClass(java.lang.String[].class); //返回字符串数组类型
// 给方法传递参数,并且调用方法 ,如果无参,则new Obe
String[] result = (String[]) call.invoke(new Object[]{paramValues[0]});
// 打印返回值
System.out.println("result is " + result.toString());
if (result != null && result.length > 0) {
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
} catch (Exception e) {
System.err.println(e.toString());
}
}
/**
* Http调用
*
* @param path
* @param stringObject
*/
public static String getHttpClient(String path, String stringObject, String up) {
CloseableHttpClient httpclient = HttpClients.createDefault();
String content = "";
// 创建HttpGet请求,相当于在浏览器输入地址
HttpPost httpPost = new HttpPost(path);
//请求头:1,请求格式 2,用户名:密码基础认证
httpPost.addHeader("Content-Type", "application/json");
byte[] encodeBase = Base64.encodeBase64(up.getBytes());
String authorization = new String(encodeBase);
authorization = "Basic " + authorization;
httpPost.addHeader("Authorization", authorization);
//把请求体json字符串封装成StringEntity
StringEntity stringEntity = new StringEntity(stringObject, "utf-8");
stringEntity.setContentEncoding("UTF-8");
httpPost.setEntity(stringEntity);
CloseableHttpResponse response = null;
try {
// 执行请求,相当于敲完地址后按下回车。获取响应
response = httpclient.execute(httpPost);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析响应,获取数据
content = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (response != null) {
// 关闭资源
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭浏览器
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return content;
}
}
**********************WSDL文件******************************
This XML file does not appear to have any style information associated with it. The document tree is shown below.