package com.ruoyi.message.sms.provider.ls;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.google.gson.Gson;
|
import com.ruoyi.common.utils.OkHttpExample;
|
import com.ruoyi.common.utils.uuid.IdUtils;
|
import com.ruoyi.message.MessageChannel;
|
import com.ruoyi.message.SendResult;
|
import com.ruoyi.message.sms.AbstractSmsSender;
|
import com.ruoyi.message.sms.SmsSendRequest;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.stereotype.Component;
|
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
|
/**
|
* 丽水短信发送方({@code ls} 通道,丽水 13 家医院)。
|
* <p>
|
* 对接特征(与其他通道差异最大的一个):
|
* <ul>
|
* <li>报文为 {@code XiaoXiTou + YeWuXX.DuanXinXX} 的嵌套 JSON;</li>
|
* <li>需要先用 {@code LyraTokenUtil} 换 token,再以 header 传 token;</li>
|
* <li>机构地址/租户/发送人存在 {@code sys_config} 表的 {@code ls.msg.info} 里(按机构查询);</li>
|
* <li>成功判定为响应体 {@code Code == "0"}。</li>
|
* </ul>
|
* 代码来源:{@code RyTask.ls 分支} + {@code RyTask.getDXCode}(行为保持不变)。
|
*/
|
@Slf4j
|
@Component
|
public class LishuiSmsSender extends AbstractSmsSender {
|
|
/**
|
* 渠道 key,与 {@code spring.profiles.active=ls} 对应
|
*/
|
public static final String KEY = "ls";
|
|
private final ObjectProvider<LishuiMessageConfigProvider> configProvider;
|
|
public LishuiSmsSender(ObjectProvider<LishuiMessageConfigProvider> configProvider) {
|
this.configProvider = configProvider;
|
}
|
|
@Override
|
public String key() {
|
return KEY;
|
}
|
|
@Override
|
public String description() {
|
return "丽水短信(13家医院,token + 机构级配置)";
|
}
|
|
@Override
|
protected SendResult doSend(SmsSendRequest request) throws Exception {
|
LishuiMessageConfig config = resolveConfig(request.getOrgid());
|
if (config == null || StringUtils.isEmpty(config.getAddress())) {
|
//与线上行为一致:该机构没有配置短信地址,视为发送失败
|
return SendResult.fail(KEY, MessageChannel.SMS, "短信发送失败,该机构没有配置短信地址", null);
|
}
|
|
String token = resolveToken(request.getOrgid(), config);
|
Map<String, Object> body = buildBody(request, config);
|
|
log.info("【{}】丽水短信发送,地址:{},参数:{},机构ID:{}",
|
KEY, config.getAddress(), request, request.getOrgid());
|
String result = OkHttpExample.sendPostRequest(config.getAddress(), new Gson().toJson(body), token);
|
log.info("【{}】丽水短信发送结果:{}", KEY, result);
|
|
if (StringUtils.isEmpty(result)) {
|
return SendResult.fail(KEY, MessageChannel.SMS, "短信发送失败", result);
|
}
|
Map<String, Object> textParam = JSON.parseObject(result, Map.class);
|
Object codeObj = textParam == null ? null : textParam.get("Code");
|
String code = codeObj == null ? null : codeObj.toString();
|
if ("0".equals(code)) {
|
return SendResult.success(KEY, MessageChannel.SMS, result).withCode(code);
|
}
|
return SendResult.fail(KEY, MessageChannel.SMS, "短信发送失败", result).withCode(code);
|
}
|
|
/**
|
* 优先使用业务模块注册的 {@link LishuiMessageConfigProvider}(查 sys_config),
|
* 否则退化为代码内静态配置。
|
*/
|
private LishuiMessageConfig resolveConfig(String orgid) {
|
LishuiMessageConfigProvider provider = configProvider.getIfAvailable();
|
if (provider != null) {
|
LishuiMessageConfig config = provider.getConfig(orgid);
|
if (config != null) {
|
if (StringUtils.isEmpty(config.getOrgid())) {
|
config.setOrgid(orgid);
|
}
|
return config;
|
}
|
}
|
LishuiMessageConfig fallback = LishuiStaticConfig.fallback(orgid);
|
return fallback;
|
}
|
|
private String resolveToken(String orgid, LishuiMessageConfig config) {
|
if (StringUtils.isEmpty(config.getTokenUrl())) {
|
return null;
|
}
|
LishuiMessageConfigProvider provider = configProvider.getIfAvailable();
|
if (provider == null) {
|
log.warn("【{}】未找到 LishuiMessageConfigProvider 实现,无法换取 token,将以空 token 调用", KEY);
|
return null;
|
}
|
return provider.getToken(orgid, config.getTokenUrl());
|
}
|
|
/**
|
* 组装丽水报文:{@code XiaoXiTou + YeWuXX.DuanXinXX}(与 {@code RyTask.getDXCode} 完全一致)
|
*/
|
private Map<String, Object> buildBody(SmsSendRequest request, LishuiMessageConfig config) {
|
Map<String, Object> headerMap = new LinkedHashMap<>();
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
headerMap.put("XiaoXiID", IdUtils.simpleUUID());
|
headerMap.put("FaSongSJ", sdf.format(new Date()));
|
headerMap.put("ZuHuID", config.getZuHuId());
|
headerMap.put("ZuHuMC", config.getZuHuMc());
|
headerMap.put("FaSongJGID", config.getOrgid());
|
headerMap.put("FaSongJGMC", config.getZuHuMc());
|
headerMap.put("FaSongXTJC", "SUIFANGXT");
|
headerMap.put("FaSongXTMC", "随访系统");
|
headerMap.put("FaSongFCSJC", "ZJHES");
|
headerMap.put("XiaoXiLX", "FZ_PT_DuanXinFS");
|
headerMap.put("XiaoXiMC", "短信发送");
|
|
Map<String, Object> duanXinXX = new LinkedHashMap<>();
|
duanXinXX.put("ShouJiHM", request.getPhone());
|
duanXinXX.put("FaSongNR", request.getContent());
|
duanXinXX.put("FaSongRID", config.getSendPersonId());
|
duanXinXX.put("FaSongRXM", config.getSendPersonName());
|
|
Map<String, Object> yeWuXX = new LinkedHashMap<>();
|
yeWuXX.put("DuanXinXX", duanXinXX);
|
|
Map<String, Object> body = new LinkedHashMap<>();
|
body.put("XiaoXiTou", headerMap);
|
body.put("YeWuXX", yeWuXX);
|
return body;
|
}
|
}
|