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 家医院)。
*
* 对接特征(与其他通道差异最大的一个):
*
* - 报文为 {@code XiaoXiTou + YeWuXX.DuanXinXX} 的嵌套 JSON;
* - 需要先用 {@code LyraTokenUtil} 换 token,再以 header 传 token;
* - 机构地址/租户/发送人存在 {@code sys_config} 表的 {@code ls.msg.info} 里(按机构查询);
* - 成功判定为响应体 {@code Code == "0"}。
*
* 代码来源:{@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 configProvider;
public LishuiSmsSender(ObjectProvider 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 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 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 buildBody(SmsSendRequest request, LishuiMessageConfig config) {
Map 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 duanXinXX = new LinkedHashMap<>();
duanXinXX.put("ShouJiHM", request.getPhone());
duanXinXX.put("FaSongNR", request.getContent());
duanXinXX.put("FaSongRID", config.getSendPersonId());
duanXinXX.put("FaSongRXM", config.getSendPersonName());
Map yeWuXX = new LinkedHashMap<>();
yeWuXX.put("DuanXinXX", duanXinXX);
Map body = new LinkedHashMap<>();
body.put("XiaoXiTou", headerMap);
body.put("YeWuXX", yeWuXX);
return body;
}
}