|
@@ -0,0 +1,216 @@
|
|
|
+package thyyxxk.webserver.service.ca;
|
|
|
+
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.dtflys.forest.Forest;
|
|
|
+import com.dtflys.forest.http.ForestRequest;
|
|
|
+import lombok.Data;
|
|
|
+import lombok.EqualsAndHashCode;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import thyyxxk.webserver.config.exception.BizException;
|
|
|
+import thyyxxk.webserver.config.exception.ExceptionEnum;
|
|
|
+import thyyxxk.webserver.constants.YesOrNo;
|
|
|
+import thyyxxk.webserver.entity.ResultVo;
|
|
|
+import thyyxxk.webserver.entity.ca.CaData;
|
|
|
+import thyyxxk.webserver.entity.ca.CaReturn;
|
|
|
+import thyyxxk.webserver.entity.ca.CaSendParams;
|
|
|
+import thyyxxk.webserver.entity.ca.CaSingBizSnReturnData;
|
|
|
+import thyyxxk.webserver.entity.login.UserInfo;
|
|
|
+import thyyxxk.webserver.service.redislike.RedisLikeService;
|
|
|
+import thyyxxk.webserver.utils.ResultVoUtil;
|
|
|
+
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.net.URLDecoder;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class CaServer {
|
|
|
+
|
|
|
+ private final CaData caData;
|
|
|
+ private final String SUCCRSS = "success";
|
|
|
+ private final RedisLikeService redisLikeService;
|
|
|
+
|
|
|
+ public CaServer(CaData caData, RedisLikeService redisLikeService) {
|
|
|
+ this.caData = caData;
|
|
|
+ this.redisLikeService = redisLikeService;
|
|
|
+ }
|
|
|
+
|
|
|
+ @EqualsAndHashCode(callSuper = true)
|
|
|
+ @Data
|
|
|
+ public static class Send extends CaSendParams {
|
|
|
+ private String id;
|
|
|
+ private String msg;
|
|
|
+ private String desc;
|
|
|
+ private Integer count = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<CaReturn.CaData> sendBatchByCode(Send send) {
|
|
|
+ List<CaReturn.CaData> returnValue = new ArrayList<>();
|
|
|
+ for (int i = 0; i < send.getCount(); i++) {
|
|
|
+ returnValue.add(sendByCode(send));
|
|
|
+ }
|
|
|
+ return returnValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CaReturn.CaData sendByCode(Send send) {
|
|
|
+ UserInfo userInfoByCode = redisLikeService.getUserInfoByCode(send.getId());
|
|
|
+ send.setBizSn(IdUtil.simpleUUID());
|
|
|
+ CaReturn push = push(send);
|
|
|
+ signatureAuthentication(send, push);
|
|
|
+ String timeStamp = generateTimestampByInData(send);
|
|
|
+ push.getData().setTimeStamp(timeStamp);
|
|
|
+ push.getData().setBizSn(send.getBizSn());
|
|
|
+ push.getData().setSignature("http://172.16.32.167:8077/doctorSignatureImage/" + send.getId() + ".png");
|
|
|
+ push.getData().setName(userInfoByCode.getName());
|
|
|
+ return push.getData();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 推送用户签名
|
|
|
+ *
|
|
|
+ * @param send
|
|
|
+ * @return 返回值
|
|
|
+ */
|
|
|
+ private CaReturn push(Send send) {
|
|
|
+ CaReturn caReturn;
|
|
|
+ try {
|
|
|
+ CaData.MobileApp app = caData.getMobileApp();
|
|
|
+ ForestRequest<?> post = Forest.post(app.getUrl() + "/v1/push/sign");
|
|
|
+ send.setAppId(app.getAppId());
|
|
|
+ send.setMsg(CaUtils.GetSHA256FormString(send.getMsg()));
|
|
|
+ send.setMsgWrapper("0");
|
|
|
+ send.setUrl(URLEncoder.encode("http://127.0.0.1/", "UTF-8"));
|
|
|
+ send.setMode("redirect");
|
|
|
+ send.setSign(CaUtils.getSign(app.getPrivatekey(), send.getMsg()));
|
|
|
+ String execute = post.addBody(send).execute(String.class);
|
|
|
+ String decode = URLDecoder.decode(execute, "UTF-8");
|
|
|
+ log.info("返回数据:{}", decode);
|
|
|
+ caReturn = JSONUtil.toBean(decode, CaReturn.class);
|
|
|
+ if (!SUCCRSS.equals(caReturn.getRet())) {
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败。" + caReturn.getMsg());
|
|
|
+ }
|
|
|
+ if (Integer.valueOf(1).equals(caReturn.getData().getIsTrust())) {
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败,请用户打开免密签名。");
|
|
|
+ }
|
|
|
+ if (Integer.valueOf(2).equals(caReturn.getData().getIsTrust())) {
|
|
|
+ return caReturn;
|
|
|
+ }
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败。" + caReturn.getMsg());
|
|
|
+ } catch (UnsupportedEncodingException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败。" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 认证签名
|
|
|
+ *
|
|
|
+ * @param send
|
|
|
+ * @param caReturn
|
|
|
+ */
|
|
|
+ private void signatureAuthentication(Send send, CaReturn caReturn) {
|
|
|
+ CaData.SignAuthentication signData = caData.getSignAuthentication();
|
|
|
+ CaWSDL caWSDL = new CaWSDL(signData.getUrl());
|
|
|
+ String replace = getVerifySignDataParams(send, caReturn, signData);
|
|
|
+ JSONObject rst = caWSDL.invoke("verifySignData", replace);
|
|
|
+ log.info("认证签名xml:{}\n认证签名返回值:{}\n", replace, rst.toString());
|
|
|
+ Integer code = rst.getByPath("Root.RetCode", Integer.class);
|
|
|
+ if (!YesOrNo.YES.getCode().equals(code)) {
|
|
|
+ String msg = rst.getByPath("Root.RetMsg", String.class);
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static @NotNull String getVerifySignDataParams(Send send, CaReturn caReturn, CaData.SignAuthentication signData) {
|
|
|
+ String request = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
|
|
|
+ "<Root>\n" +
|
|
|
+ "\t<AppCode>${AppCode}</AppCode>\n" +
|
|
|
+ "\t<AppPWD>${AppPWD}</AppPWD>\n" +
|
|
|
+ "\t<Request>\n" +
|
|
|
+ "\t\t<Cert>${Cert}</Cert>\n" +
|
|
|
+ "\t\t<SignAlg>${SignAlg}</SignAlg>\n" +
|
|
|
+ "\t\t<InData>${InData}</InData>\n" +
|
|
|
+ "\t\t<SignData>${SignData}</SignData>\n" +
|
|
|
+ "\t</Request>\n" +
|
|
|
+ "</Root>";
|
|
|
+
|
|
|
+ return request.replace("${AppCode}", signData.getAppCode())
|
|
|
+ .replace("${AppPWD}", signData.getAppPwd())
|
|
|
+ .replace("${Cert}", caReturn.getData().getCert())
|
|
|
+ .replace("${SignAlg}", signData.getSignAig())
|
|
|
+ .replace("${InData}", send.getMsg())
|
|
|
+ .replace("${SignData}", caReturn.getData().getSignValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 认证时间戳并返回
|
|
|
+ *
|
|
|
+ * @param send 数据
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private String generateTimestampByInData(Send send) {
|
|
|
+ String data = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
|
|
|
+ "<Root>\n" +
|
|
|
+ "\t<AppCode>${AppCode}</AppCode>\n" +
|
|
|
+ "\t<AppPWD>${AppPWD}</AppPWD>\n" +
|
|
|
+ "\t<Request>\n" +
|
|
|
+ "\t\t<InData>${InData}</InData>\n" +
|
|
|
+ "<HashAlg>${HashAlg}</HashAlg>\n" +
|
|
|
+ "<CertReq>${CertReq}</CertReq>\n" +
|
|
|
+ "\t</Request>\n" +
|
|
|
+ "</Root>";
|
|
|
+
|
|
|
+ CaData.TimestampAuthentication timeData = caData.getTimestampAuthentication();
|
|
|
+ String request = data.replace("${AppCode}", timeData.getAppCode())
|
|
|
+ .replace("${AppPWD}", timeData.getAppPwd())
|
|
|
+ .replace("${InData}", send.getMsg())
|
|
|
+ .replace("${HashAlg}", "SHA256")
|
|
|
+ .replace("${CertReq}", "true");
|
|
|
+
|
|
|
+ CaWSDL caWSDL = new CaWSDL(timeData.getUrl());
|
|
|
+ JSONObject ret = caWSDL.invoke("generateTimestampByInData", request);
|
|
|
+ Integer code = ret.getByPath("Root.RetCode", Integer.class);
|
|
|
+ log.info("认证时间戳xml:{}\n认证时间戳返回值:{}\n", request, ret);
|
|
|
+ if (code != 1) {
|
|
|
+ String msg = ret.getByPath("Root.RetMsg", String.class);
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, msg);
|
|
|
+ }
|
|
|
+ return ret.getByPath("Root.Response.TimeStamp", String.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ResultVo<CaSingBizSnReturnData> getSignInfoByBizSn(String bizSn) {
|
|
|
+ CaData.MobileApp app = caData.getMobileApp();
|
|
|
+ ForestRequest<?> post = Forest.post(app.getUrl() + "/v1/sign/info/" + bizSn);
|
|
|
+ CaSendParams send = new CaSendParams();
|
|
|
+ send.setAppId(app.getAppId());
|
|
|
+
|
|
|
+ String indata = "appId=" + app.getAppId() + "&bizSn=" + bizSn;
|
|
|
+ String sign = CaUtils.getSign(app.getPrivatekey(), indata);
|
|
|
+ send.setSign(sign);
|
|
|
+
|
|
|
+ String ret = post.addBody(send).execute(String.class);
|
|
|
+
|
|
|
+ CaSingBizSnReturnData execute = JSONUtil.toBean(ret, CaSingBizSnReturnData.class);
|
|
|
+ if (SUCCRSS.equals(execute.getRet())) {
|
|
|
+ CaSingBizSnReturnData.SingData data = execute.getData();
|
|
|
+ try {
|
|
|
+ data.setSignData(URLDecoder.decode(data.getSignData(), "UTF-8"));
|
|
|
+ data.setCert(URLDecoder.decode(data.getCert(), "UTF-8"));
|
|
|
+ data.setSeal(URLDecoder.decode(data.getSeal(), "UTF-8"));
|
|
|
+ } catch (UnsupportedEncodingException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, "解码失败请联系管理员" + bizSn);
|
|
|
+ }
|
|
|
+ return ResultVoUtil.success(execute);
|
|
|
+ }
|
|
|
+ return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, execute.getMsg());
|
|
|
+ }
|
|
|
+
|
|
|
+}
|